diff --git a/testing/algorithms/ArithmeticTest.cpp b/testing/algorithms/ArithmeticTest.cpp index bad153d..d7d73a3 100644 --- a/testing/algorithms/ArithmeticTest.cpp +++ b/testing/algorithms/ArithmeticTest.cpp @@ -1,352 +1,344 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "../core/DummyDoseAccessor.h" #include "../core/DummyMaskAccessor.h" #include "../core/DummyMutableDoseAccessor.h" -#include "rttbDoseAccessorInterface.h" -#include "rttbMutableDoseAccessorInterface.h" -#include "rttbMutableMaskAccessorInterface.h" #include "rttbArithmetic.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" #include "rttbGenericMutableMaskAccessor.h" -#include "rttbMaskAccessorInterface.h" namespace rttb { namespace testing { typedef core::DoseAccessorInterface::Pointer DoseAccessorPointer; typedef core::MutableDoseAccessorInterface::Pointer MutableDoseAccessorPointer; typedef DummyMaskAccessor::MaskVoxelListPointer MaskVoxelListPointer; typedef DummyMaskAccessor::MaskVoxelList MaskVoxelList; typedef core::MaskAccessorInterface::Pointer MaskAccessorPointer; typedef core::MutableMaskAccessorInterface::Pointer MutableMaskAccessorPointer; /*! @brief ArithmeticTest - tests arithmetic combinations of accessors 1) test dose-dose operations 2) test dose-mask operations 3) test mask-mask operations 4) test convenience functions */ int ArithmeticTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; // initialize accessors for arithmetic //DOSE: //Null pointers DoseAccessorPointer spDoseNull; MutableDoseAccessorPointer spMutableDoseNull; //dose with random values between 0 and 100 boost::shared_ptr spTestDoseAccessor1 = boost::make_shared(); DoseAccessorPointer spDoseAccessor1(spTestDoseAccessor1); //generate a 2nd dose with fixed values core::GeometricInfo geoInfo = spDoseAccessor1->getGeometricInfo(); DoseTypeGy valFix = 101; // to ensure values are larger than 100 on adding std::vector dose2Vals(geoInfo.getNumberOfVoxels(), valFix); boost::shared_ptr spTestDoseAccessor2 = boost::make_shared (dose2Vals, geoInfo); DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); //generate result acessor std::vector doseResultVals(geoInfo.getNumberOfVoxels(), -1); boost::shared_ptr spTestMutableDoseAccessor = boost::make_shared(doseResultVals, geoInfo); MutableDoseAccessorPointer spMutableDoseAccessor(spTestMutableDoseAccessor); // different geometricInfo core::GeometricInfo geoInfo2 = geoInfo; geoInfo2.setNumColumns(5); geoInfo2.setNumRows(5); geoInfo2.setNumSlices(5); std::vector dose3Vals(geoInfo2.getNumberOfVoxels(), valFix); boost::shared_ptr spTestDoseAccessor3 = boost::make_shared (dose3Vals, geoInfo2); DoseAccessorPointer spDoseAccessorDiffGeoInfo(spTestDoseAccessor3); boost::shared_ptr spTestMutableDoseAccessor2 = boost::make_shared(dose3Vals, geoInfo2); MutableDoseAccessorPointer spMutableDoseAccessorDiffGeoInfo(spTestMutableDoseAccessor2); //MASK: //null pointer MaskAccessorPointer spMaskAccessorNull; MutableMaskAccessorPointer spMutableMaskAccessorNull; MaskVoxelList voxelList; FractionType aVolumeFraction = 1; VoxelGridID aVoxelGridID = 10; //generate a dummy mask while (aVoxelGridID < geoInfo.getNumberOfVoxels() && aVoxelGridID <= 30) { voxelList.push_back(core::MaskVoxel(aVoxelGridID, aVolumeFraction)); ++aVoxelGridID; } MaskVoxelListPointer voxelListPtr = boost::make_shared(voxelList); boost::shared_ptr dummyMask1 = boost::make_shared(geoInfo, voxelListPtr); MaskAccessorPointer spMaskAccessor1(dummyMask1); MaskVoxelList voxelList2; aVoxelGridID = 20; //generate a 2nd dummy mask that partly overlaps with the 1st one while (aVoxelGridID < geoInfo.getNumberOfVoxels() && aVoxelGridID <= 40) { voxelList2.push_back(core::MaskVoxel(aVoxelGridID, aVolumeFraction)); ++aVoxelGridID; } MaskVoxelListPointer voxelListPtr2 = boost::make_shared(voxelList2); boost::shared_ptr dummyMask2 = boost::make_shared(geoInfo, voxelListPtr2); MaskAccessorPointer spMaskAccessor2(dummyMask2); // result accessor boost::shared_ptr mMask1 = boost::make_shared(geoInfo); MutableMaskAccessorPointer spMutableMask(mMask1); // different geometricInfo boost::shared_ptr spDummyMaskDiffGeoInfo = boost::make_shared (geoInfo2, voxelListPtr2); MaskAccessorPointer spMaskAccessorDiffGeoInfo(spDummyMaskDiffGeoInfo); boost::shared_ptr mMask2 = boost::make_shared(geoInfo2); MutableMaskAccessorPointer spMutableMaskDiffGeoInfo(mMask2); // 1) test dose-dose operations //ADD algorithms::arithmetic::doseOp::Add addOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, addOP)); VoxelGridID id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseNull, spMutableDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseNull, spDoseAccessor2, spMutableDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseNull, addOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessorDiffGeoInfo, spMutableDoseAccessor, addOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessorDiffGeoInfo, spDoseAccessor2, spMutableDoseAccessor, addOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessorDiffGeoInfo, addOP), core::InvalidParameterException); //ADD_WEIGHTED algorithms::arithmetic::doseOp::AddWeighted addWOP(1, 2); CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, addWOP)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + 2 * valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + 2 * valFix, spMutableDoseAccessor->getValueAt(id)); //MULTIPLY algorithms::arithmetic::doseOp::Multiply multiplyOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, multiplyOP)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) * valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) * valFix, spMutableDoseAccessor->getValueAt(id)); // 2) test dose-mask operations //MULTIPLY algorithms::arithmetic::doseMaskOp::Multiply multOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessor, multOP)); core::MaskVoxel mVoxel(0); id = 5; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); spMaskAccessor1->getMaskAt(id, mVoxel); CHECK_EQUAL(spMutableDoseAccessor->getValueAt(id), mVoxel.getRelevantVolumeFraction()); id = 15; CHECK_EQUAL(valFix, spMutableDoseAccessor->getValueAt(id)); id = 35; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spMaskAccessorNull, spMutableDoseAccessor, multOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseNull, spDoseAccessor2, spMutableDoseAccessor, multOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseNull, multOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessorDiffGeoInfo, spMutableDoseAccessor, multOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessorDiffGeoInfo, spMaskAccessor1, spMutableDoseAccessor, multOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessorDiffGeoInfo, multOP), core::InvalidParameterException); // 3) test mask-mask operations //ADD algorithms::arithmetic::maskOp::Add maskAddOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor2, spMutableMask, maskAddOP)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessorNull, spMutableMask, maskAddOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessorNull, spMaskAccessor2, spMutableMask, maskAddOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor1, spMutableMaskAccessorNull, maskAddOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessorDiffGeoInfo, spMutableMask, maskAddOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessorDiffGeoInfo, spMaskAccessor2, spMutableMask, maskAddOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor1, spMutableMaskDiffGeoInfo, maskAddOP), core::InvalidParameterException); //SUBTRACT algorithms::arithmetic::maskOp::Subtract maskSubOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor2, spMutableMask, maskSubOP)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); // 4) test convenience functions // tests are similar to explicit calls CHECK_NO_THROW(algorithms::arithmetic::add(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); CHECK_NO_THROW(algorithms::arithmetic::add(spMaskAccessor1, spMaskAccessor2, spMutableMask)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); CHECK_NO_THROW(algorithms::arithmetic::subtract(spMaskAccessor1, spMaskAccessor2, spMutableMask)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); CHECK_NO_THROW(algorithms::arithmetic::multiply(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessor)); id = 5; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); spMaskAccessor1->getMaskAt(id, mVoxel); CHECK_EQUAL(spMutableDoseAccessor->getValueAt(id), mVoxel.getRelevantVolumeFraction()); id = 15; CHECK_EQUAL(valFix, spMutableDoseAccessor->getValueAt(id)); id = 35; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); RETURN_AND_REPORT_TEST_SUCCESS; } } } \ No newline at end of file diff --git a/testing/algorithms/BinaryFunctorAccessorTest.cpp b/testing/algorithms/BinaryFunctorAccessorTest.cpp index 301933f..61f389b 100644 --- a/testing/algorithms/BinaryFunctorAccessorTest.cpp +++ b/testing/algorithms/BinaryFunctorAccessorTest.cpp @@ -1,125 +1,119 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbDoseAccessorInterface.h" -#include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbArithmetic.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" #include "rttbBinaryFunctorAccessor.h" namespace rttb { namespace testing { typedef core::DoseAccessorInterface::Pointer DoseAccessorPointer; typedef algorithms::BinaryFunctorAccessor BinaryFunctorAccessorAddType; typedef algorithms::BinaryFunctorAccessor BinaryFunctorAccessorAddWeightedType; /*! @brief BinaryFunctorAccessorTest - tests functors of two accessors 1) test constructor 2) test getDoseAt */ int BinaryFunctorAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } if (argc > 2) { RTDOSE2_FILENAME = argv[2]; } DoseAccessorPointer spDoseAccessorNull; DoseAccessorPointer spDoseAccessor = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE_FILENAME.c_str()).generateDoseAccessor(); DoseAccessorPointer spDoseAccessor2 = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE2_FILENAME.c_str()).generateDoseAccessor(); algorithms::arithmetic::doseOp::Add addOP; algorithms::arithmetic::doseOp::AddWeighted addWeightedOP(1.0, 10.0); algorithms::arithmetic::doseOp::AddWeighted addWeightedTwoOP(2.0, 2.0); //1) Check constructor CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessorNull, spDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessorNull, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessorNull, spDoseAccessorNull, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessor2, addOP), core::InvalidParameterException); CHECK_NO_THROW(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessor, addOP)); CHECK_NO_THROW(BinaryFunctorAccessorAddWeightedType(spDoseAccessor, spDoseAccessor, addWeightedOP)); auto spBinaryFunctorDoseAccessorAdd = boost::make_shared(spDoseAccessor, spDoseAccessor, addOP); auto spBinaryFunctorDoseAccessorAddWeighted = boost::make_shared(spDoseAccessor, spDoseAccessor, addWeightedOP); auto spBinaryFunctorDoseAccessorAddWeightedTwo = boost::make_shared(spDoseAccessor, spDoseAccessor, addWeightedTwoOP); //2) Test getDoseAt() int lastIndex = spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumberOfVoxels() - 1; VoxelGridID aId[3] = { 5, 6067, lastIndex }; VoxelGridIndex3D aIndex[3] = {VoxelGridIndex3D(5, 0, 0), VoxelGridIndex3D(37, 0, 2), VoxelGridIndex3D(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumColumns() - 1, spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumRows() - 1, spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumSlices() - 1)}; for (int i = 0; i < 3; ++i) { CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i]), 4.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aId[i]), 22.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIndex[i]), spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i])); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIndex[i]), spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aId[i])); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i]) * 2.0, spBinaryFunctorDoseAccessorAddWeightedTwo->getValueAt(aId[i])); } VoxelGridID aIdInvalid(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumberOfVoxels()); VoxelGridIndex3D aIndexInvalid(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumColumns(), spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumRows(), spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumSlices()); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIdInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIndexInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIdInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIndexInvalid), -1.0); RETURN_AND_REPORT_TEST_SUCCESS; } } } \ No newline at end of file diff --git a/testing/algorithms/DoseStatisticsCalculatorTest.cpp b/testing/algorithms/DoseStatisticsCalculatorTest.cpp index 682a124..e9a7765 100644 --- a/testing/algorithms/DoseStatisticsCalculatorTest.cpp +++ b/testing/algorithms/DoseStatisticsCalculatorTest.cpp @@ -1,385 +1,379 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include -#include "litCheckMacros.h" - -#include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" -#include "rttbDoseIteratorInterface.h" #include "rttbNullPointerException.h" #include "rttbDoseStatisticsCalculator.h" -#include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include "rttbDataNotAvailableException.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbBoostMaskAccessor.h" #include "rttbGenericMaskedDoseIterator.h" #include "../io/other/CompareDoseStatistic.h" #include "../../code/io/other/rttbDoseStatisticsXMLReader.h" #include "../core/DummyDoseAccessor.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::Pointer DoseIteratorPointer; typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; typedef rttb::algorithms::DoseStatistics::Pointer DoseStatisticsPointer; /*! @brief DoseStatisticsCalculatorTest - test the API of DoseStatisticsCalculator 1) test constructors 2) test setDoseIterator 3) test calculateDoseSatistics 4) get statistical values */ int DoseStatisticsCalculatorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string referenceXMLFilename; std::string doseFilename, structFilename; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); DoseIteratorPointer spDoseIteratorNull; if (argc > 3) { referenceXMLFilename = argv[1]; doseFilename = argv[2]; structFilename = argv[3]; } //1) test constructors // the values cannot be accessed from outside, therefore correct default values are not tested CHECK_THROW_EXPLICIT(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator( spDoseIteratorNull), core::NullPointerException); CHECK_NO_THROW(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator)); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); //2) test setDoseIterator //3) test calculateDoseStatistics DoseStatisticsPointer theStatistics; //simple dose statistics CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics()); CHECK_EQUAL(theStatistics->getMinimumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getMaximumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getVx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getDx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getVx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMaxOHx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMOHx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMOCx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMinOCx().getAllValues().empty(), true); //check default values for computeComplexMeasures=true DoseStatisticsPointer theStatisticsDefault; myDoseStatsCalculator.setMultiThreading(true); CHECK_NO_THROW(theStatisticsDefault = myDoseStatsCalculator.calculateDoseStatistics(true)); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.02 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.05 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.1 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.9 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.95 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.98 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.02 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.05 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.1 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.9 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.95 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.98 * theStatisticsDefault->getVolume())); //check manually set reference dose and the default x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.1 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx().getValue(0.1 * 100.0)); CHECK_NO_THROW(theStatistics->getDx().getValue(0.1 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOHx().getValue(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOCx().getValue(0.98 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //check manually set x values std::vector precomputeDoseValues, precomputeVolumeValues, additionalValues, faultyValues; precomputeDoseValues.push_back(0.01); precomputeDoseValues.push_back(0.02); precomputeDoseValues.push_back(0.05); precomputeVolumeValues.push_back(0.9); precomputeVolumeValues.push_back(0.95); precomputeVolumeValues.push_back(0.99); additionalValues.push_back(0.03); additionalValues.push_back(0.04); faultyValues.push_back(2); CHECK_THROW_EXPLICIT(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, faultyValues), core::InvalidParameterException); CHECK_THROW_EXPLICIT(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(faultyValues, precomputeVolumeValues), core::InvalidParameterException); CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues)); CHECK_NO_THROW(theStatistics->getVx().getValue(0.01 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx().getValue(0.02 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx().getValue(0.05 * theStatistics->getMaximum())); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.03 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.99 * theStatistics->getVolume())); CHECK_THROW_EXPLICIT(theStatistics->getDx().getValue(0.04 * theStatistics->getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(myDoseStatsCalculator.addPrecomputeValues(faultyValues), core::InvalidParameterException); CHECK_NO_THROW(myDoseStatsCalculator.addPrecomputeValues(additionalValues)); CHECK_NO_THROW(myDoseStatsCalculator.recalculateDoseStatistics()); CHECK_NO_THROW(theStatistics->getVx().getValue(0.03 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.04 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getVx().getValue(0.02 * theStatistics->getMaximum()), theStatisticsDefault->getVx().getValue(0.02 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getVx().getValue(0.05 * theStatistics->getMaximum()), theStatisticsDefault->getVx().getValue(0.05 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume()), theStatisticsDefault->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getDx().getValue(0.95 * theStatistics->getVolume()), theStatisticsDefault->getDx().getValue(0.95 * theStatistics->getVolume())); //check manually set reference dose and x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues, 100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.01 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx().getValue(0.01 * 100.0)); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //MOHx, MOCx, MaxOHx and MinOCx are computed analogous to Dx, they will not be checked. //4) get statistical values CHECK_EQUAL(theStatistics->getNumberOfVoxels(), doseVals->size()); //compute simple statistical values (min, mean, max, stddev) for comparison DoseStatisticType maximum = 0; DoseStatisticType minimum = 1000000; DoseStatisticType mean = 0; DoseStatisticType variance = 0; std::vector::const_iterator doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (maximum < *doseIt) { maximum = *doseIt; } if (minimum > *doseIt) { minimum = *doseIt; } mean += *doseIt; ++doseIt; } mean /= doseVals->size(); doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { variance += pow(*doseIt - mean, 2); ++doseIt; } variance /= doseVals->size(); DoseStatisticType stdDev = pow(variance, 0.5); //we have some precision problems here... double errorConstantLarger = 1e-2; CHECK_EQUAL(theStatistics->getMaximum(), maximum); CHECK_EQUAL(theStatistics->getMinimum(), minimum); CHECK_CLOSE(theStatistics->getMean(), mean, errorConstantLarger); CHECK_CLOSE(theStatistics->getStdDeviation(), stdDev, errorConstantLarger); CHECK_CLOSE(theStatistics->getVariance(), variance, errorConstantLarger); //check for complex doseStatistics (maximumPositions, minimumPositions, Vx, Dx, MOHx, MOCx, MAXOHx, MinOCx) unsigned int nMax = 0, nMin = 0; doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (*doseIt == theStatistics->getMaximum()) { nMax++; } if (*doseIt == theStatistics->getMinimum()) { nMin++; } ++doseIt; } //only 100 positions are stored if (nMax > 100) { nMax = 100; } if (nMin > 100) { nMin = 100; } auto maximaPositions = theStatistics->getMaximumVoxelPositions(); auto minimaPositions = theStatistics->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->size(), nMax); CHECK_EQUAL(minimaPositions->size(), nMin); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics->getMinimum()); } //generate specific example dose maximum = 9.5; minimum = 2.5; mean = 6; int sizeTemplate = 500; std::vector aDoseVector; for (int i = 0; i < sizeTemplate; i++) { aDoseVector.push_back(maximum); aDoseVector.push_back(minimum); } core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); geoInfo.setNumRows(20); geoInfo.setNumColumns(10); geoInfo.setNumSlices(5); boost::shared_ptr spTestDoseAccessor2 = boost::make_shared(aDoseVector, geoInfo); DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); boost::shared_ptr spTestDoseIterator2 = boost::make_shared(spDoseAccessor2); DoseIteratorPointer spDoseIterator2(spTestDoseIterator2); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator2(spDoseIterator2); DoseStatisticsPointer theStatistics3 = myDoseStatsCalculator2.calculateDoseStatistics(); CHECK_EQUAL(theStatistics3->getMaximum(), maximum); CHECK_EQUAL(theStatistics3->getMinimum(), minimum); CHECK_EQUAL(theStatistics3->getMean(), mean); maximaPositions = theStatistics3->getMaximumVoxelPositions(); minimaPositions = theStatistics3->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->empty(), false); CHECK_EQUAL(minimaPositions->empty(), false); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics3->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics3->getMinimum()); } // compare with actual XML io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator(doseFilename.c_str()); core::DoseAccessorInterface::Pointer doseAccessorPointer(doseAccessorGenerator.generateDoseAccessor()); rttb::io::dicom::DicomFileStructureSetGenerator structAccessorGenerator(structFilename.c_str()); structAccessorGenerator.setStructureLabelFilterActive(true); structAccessorGenerator.setFilterRegEx("Heart"); core::StructureSet::Pointer structureSetGeneratorPointer = structAccessorGenerator.generateStructureSet(); CHECK_EQUAL(structureSetGeneratorPointer->getNumberOfStructures(), 1); core::MaskAccessorInterface::Pointer maskAccessorPointer = boost::make_shared (structureSetGeneratorPointer->getStructure(0), doseAccessorPointer->getGeometricInfo(), true); maskAccessorPointer->updateMask(); boost::shared_ptr maskedDoseIterator = boost::make_shared(maskAccessorPointer, doseAccessorPointer); rttb::core::DoseIteratorInterface::Pointer doseIteratorPointer(maskedDoseIterator); rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculator(doseIteratorPointer); DoseStatisticsPointer doseStatisticsActual = doseStatisticsCalculator.calculateDoseStatistics(14.0); io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); auto doseStatisticsExpected = readerDefaultExpected.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsExpected, doseStatisticsActual)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/algorithms/DoseStatisticsTest.cpp b/testing/algorithms/DoseStatisticsTest.cpp index 15a8059..64c0a47 100644 --- a/testing/algorithms/DoseStatisticsTest.cpp +++ b/testing/algorithms/DoseStatisticsTest.cpp @@ -1,245 +1,239 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include -#include - #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbDoseStatistics.h" #include "rttbDataNotAvailableException.h" - -#include "rttbVolumeToDoseMeasureCollection.h" +#include "rttbDoseStatistics.h" namespace rttb { namespace testing { typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; /*! @brief DoseStatisticsTest - test the API of DoseStatistics 1) test constructors 2) test setters 3) test getters of complex statistics (with stored key and without stored key) */ int DoseStatisticsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; DoseStatisticType minimum = 1.0; DoseStatisticType mean = 5.5; DoseStatisticType maximum = 108.2; DoseStatisticType stdDeviation = 10.1; unsigned int numVoxels = 100000; VolumeType volume = numVoxels * (0.5 * 0.5 * 0.5); std::vector > minVoxels; std::vector > maxVoxels; minVoxels.push_back(std::make_pair(1.0, 11)); minVoxels.push_back(std::make_pair(1.0, 22)); minVoxels.push_back(std::make_pair(1.0, 33)); minVoxels.push_back(std::make_pair(1.0, 44)); maxVoxels.push_back(std::make_pair(108.2, 5)); maxVoxels.push_back(std::make_pair(108.2, 6)); maxVoxels.push_back(std::make_pair(108.2, 7)); maxVoxels.push_back(std::make_pair(108.2, 8)); ResultListPointer resultsMinVoxels = boost::make_shared > >(minVoxels); ResultListPointer resultsMaxVoxels = boost::make_shared > >(maxVoxels); algorithms::DoseToVolumeMeasureCollection Vx(algorithms::DoseToVolumeMeasureCollection::Vx, maximum); Vx.insertValue(1.1, 1000); Vx.insertValue(106.9, 99000); algorithms::VolumeToDoseMeasureCollection Dx(algorithms::VolumeToDoseMeasureCollection::Dx, volume); Dx.insertValue(1000, 1.1); Dx.insertValue(99000, 106.9); algorithms::VolumeToDoseMeasureCollection MOHx(algorithms::VolumeToDoseMeasureCollection::MOHx, volume); MOHx.insertValue(1000, 5); MOHx.insertValue(99000, 105.5); algorithms::VolumeToDoseMeasureCollection MOCx(algorithms::VolumeToDoseMeasureCollection::MOCx, volume); MOCx.insertValue(1000, 10); MOCx.insertValue(99000, 99); algorithms::VolumeToDoseMeasureCollection MaxOHx(algorithms::VolumeToDoseMeasureCollection::MaxOHx, volume); MaxOHx.insertValue(1000, 40); MaxOHx.insertValue(99000, 98.3); algorithms::VolumeToDoseMeasureCollection MinOCx(algorithms::VolumeToDoseMeasureCollection::MinOCx, volume); MinOCx.insertValue(1000, 25.5); MinOCx.insertValue(99000, 102.7); //1) test constructors CHECK_NO_THROW(rttb::algorithms::DoseStatistics aDoseStatistic(minimum, maximum, mean, stdDeviation, numVoxels, volume)); rttb::algorithms::DoseStatistics aDoseStatistic(minimum, maximum, mean, stdDeviation, numVoxels, volume); CHECK_EQUAL(aDoseStatistic.getMinimum(), minimum); CHECK_EQUAL(aDoseStatistic.getMaximum(), maximum); CHECK_EQUAL(aDoseStatistic.getMean(), mean); CHECK_EQUAL(aDoseStatistic.getStdDeviation(), stdDeviation); CHECK_EQUAL(aDoseStatistic.getVariance(), stdDeviation * stdDeviation); CHECK_EQUAL(aDoseStatistic.getNumberOfVoxels(), numVoxels); CHECK_EQUAL(aDoseStatistic.getVolume(), volume); //check default values for unset complex values CHECK_EQUAL(aDoseStatistic.getMaximumVoxelPositions()->empty(), true); CHECK_EQUAL(aDoseStatistic.getMinimumVoxelPositions()->empty(), true); CHECK_EQUAL(aDoseStatistic.getDx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getVx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMOHx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMOCx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMaxOHx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMinOCx().getAllValues().empty(), true); CHECK_NO_THROW(rttb::algorithms::DoseStatistics aDoseStatisticComplex(minimum, maximum, mean, stdDeviation, numVoxels, volume, resultsMaxVoxels, resultsMinVoxels, Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx)); rttb::algorithms::DoseStatistics aDoseStatisticComplex(minimum, maximum, mean, stdDeviation, numVoxels, volume, resultsMaxVoxels, resultsMinVoxels, Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx); CHECK_EQUAL(aDoseStatisticComplex.getMaximumVoxelPositions(), resultsMaxVoxels); CHECK_EQUAL(aDoseStatisticComplex.getMinimumVoxelPositions(), resultsMinVoxels); CHECK_EQUAL(aDoseStatisticComplex.getDx() == Dx, true); CHECK_EQUAL(aDoseStatisticComplex.getVx() == Vx, true); CHECK_EQUAL(aDoseStatisticComplex.getMOHx() == MOHx, true); CHECK_EQUAL(aDoseStatisticComplex.getMOCx() == MOCx, true); CHECK_EQUAL(aDoseStatisticComplex.getMaxOHx() == MaxOHx, true); CHECK_EQUAL(aDoseStatisticComplex.getMinOCx() == MinOCx, true); //2) test setters (only complex statistics have setters) CHECK_NO_THROW(aDoseStatistic.setMaximumVoxelPositions(resultsMaxVoxels)); CHECK_NO_THROW(aDoseStatistic.setMinimumVoxelPositions(resultsMinVoxels)); CHECK_NO_THROW(aDoseStatistic.setDx(::boost::make_shared(Dx))); CHECK_NO_THROW(aDoseStatistic.setVx(::boost::make_shared(Vx))); CHECK_NO_THROW(aDoseStatistic.setMOHx(::boost::make_shared(MOHx))); CHECK_NO_THROW(aDoseStatistic.setMOCx(::boost::make_shared(MOCx))); CHECK_NO_THROW(aDoseStatistic.setMaxOHx(::boost::make_shared(MaxOHx))); CHECK_NO_THROW(aDoseStatistic.setMinOCx(::boost::make_shared(MinOCx))); CHECK_EQUAL(aDoseStatistic.getMaximumVoxelPositions(), resultsMaxVoxels); CHECK_EQUAL(aDoseStatistic.getMinimumVoxelPositions(), resultsMinVoxels); CHECK_EQUAL(aDoseStatistic.getDx() == Dx, true); CHECK_EQUAL(aDoseStatistic.getVx() == Vx, true); CHECK_EQUAL(aDoseStatistic.getMOHx() == MOHx, true); CHECK_EQUAL(aDoseStatistic.getMOCx() == MOCx, true); CHECK_EQUAL(aDoseStatistic.getMaxOHx() == MaxOHx, true); CHECK_EQUAL(aDoseStatistic.getMinOCx() == MinOCx, true); //3) test getters of complex statistics(with stored key and without stored key) //getAll*() already tested in (2) Vx = algorithms::DoseToVolumeMeasureCollection(algorithms::DoseToVolumeMeasureCollection::Vx, maximum); Vx.insertValue(1.1, 1000); Vx.insertValue(5.0, 2300); Vx.insertValue(90, 90500); Vx.insertValue(107, 99000); Dx = algorithms::VolumeToDoseMeasureCollection(algorithms::VolumeToDoseMeasureCollection::Dx, volume); Dx.insertValue(1000, 1.1); Dx.insertValue(2000, 2.0); Dx.insertValue(5000, 10.8); Dx.insertValue(90000, 89.5); Dx.insertValue(98000, 104.4); Dx.insertValue(99000, 106.9); rttb::algorithms::DoseStatistics aDoseStatisticNewValues(minimum, maximum, mean, stdDeviation, numVoxels, volume); aDoseStatisticNewValues.setDx(::boost::make_shared(Dx)); aDoseStatisticNewValues.setVx(::boost::make_shared(Vx)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValue(1.1)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValue(90)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(1000)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(98000)); CHECK_EQUAL(aDoseStatisticNewValues.getVx().getValue(1.1), Vx.getAllValues().find(1.1)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx().getValue(90), Vx.getAllValues().find(90)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(1000), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(98000), Dx.getAllValues().find(98000)->second); //test if key-value combination NOT in map CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getDx().getValue(1001), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getVx().getValue(10), core::DataNotAvailableException); double closestDxKey, closestVxKey; CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(900, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(99001, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValue(10, true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(900, true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(99001, true, closestDxKey), Dx.getAllValues().find(99000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx().getValue(10, true, closestVxKey), Vx.getAllValues().find(5.0)->second); CHECK_EQUAL(closestDxKey, 99000); CHECK_EQUAL(closestVxKey, 5); // relatives only between 0 and 1 CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValueRelative(1.1 / aDoseStatistic.getReferenceDose())); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(1000 / aDoseStatistic.getVolume())); CHECK_THROW(aDoseStatisticNewValues.getVx().getValueRelative(-0.3)); CHECK_THROW(aDoseStatisticNewValues.getVx().getValueRelative(1.1)); CHECK_THROW(aDoseStatisticNewValues.getDx().getValueRelative(0.5)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(900 / aDoseStatistic.getVolume(), true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(0.5, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValueRelative(10 / aDoseStatistic.getReferenceDose(), true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValueRelative(900 / aDoseStatistic.getVolume(), true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx().getValueRelative(10 / aDoseStatistic.getReferenceDose(), true, closestVxKey), Vx.getAllValues().find(5.0)->second); CHECK_EQUAL(closestVxKey, 5); //equal distance to two values. First value is returned. CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(1500, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx().getValue(98.5, true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(1500, true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx().getValue(98.5, true, closestVxKey), Vx.getAllValues().find(90.0)->second); CHECK_EQUAL(closestDxKey, 1000); CHECK_EQUAL(closestVxKey, 90.0); double dummy; CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValue(25), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValue(9999), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValue(25, true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValue(9999, true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValueRelative(25 / aDoseStatistic.getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValueRelative(9999 / aDoseStatistic.getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValueRelative(25 / aDoseStatistic.getVolume(), true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValueRelative(9999 / aDoseStatistic.getVolume(), true, dummy), core::DataNotAvailableException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp b/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp index 0d1cb9c..e61dcc4 100644 --- a/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp @@ -1,92 +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. // //------------------------------------------------------------------------ -#include - +#include "boost/filesystem.hpp" #include "litCheckMacros.h" -#include "boost/filesystem.hpp" +#include namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int BioModelCalcInvalidParametersTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string bioModelCalcExecutable; if (argc > 1) { bioModelCalcExecutable = argv[1]; } boost::filesystem::path callingPath(_callingAppPath); std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; //call with too few parameters std::string toofewParametersCommand = bioModelCalcExeWithPath; toofewParametersCommand += " test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); toofewParametersCommand = bioModelCalcExeWithPath; toofewParametersCommand += " test test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); toofewParametersCommand = bioModelCalcExeWithPath; toofewParametersCommand += " -d test"; toofewParametersCommand += " -o test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); //call with invalid model std::string minimalCLI = bioModelCalcExeWithPath + " test test -p 1.0 1.0 "; std::string invalidModelOption = minimalCLI; invalidModelOption += "-m wrongModel"; std::cout << "Command line call: " + invalidModelOption << std::endl; CHECK_EQUAL(system(invalidModelOption.c_str()) != 0, true); //call with only one parameter std::string toofewModelParameterOption = bioModelCalcExeWithPath + " test test -p 1.0"; std::cout << "Command line call: " + toofewModelParameterOption << std::endl; CHECK_EQUAL(system(toofewModelParameterOption.c_str()) != 0, true); toofewModelParameterOption = bioModelCalcExeWithPath + " test test -a parameterMapsTest"; std::cout << "Command line call: " + toofewModelParameterOption << std::endl; CHECK_EQUAL(system(toofewModelParameterOption.c_str()) != 0, true); //call with invalid dose load option std::string invalidDoseLoadOption = minimalCLI; invalidDoseLoadOption += "-t invalidLoadStyleOption"; std::cout << "Command line call: " + invalidDoseLoadOption << std::endl; CHECK_EQUAL(system(invalidDoseLoadOption.c_str()) != 0, true); //call with negative dose scaling std::string negativeDoseScalingCommand = minimalCLI; negativeDoseScalingCommand += "-e -1.0"; std::cout << "Command line call: " + negativeDoseScalingCommand << std::endl; CHECK_EQUAL(system(negativeDoseScalingCommand.c_str()) != 0, true); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp index c683480..2b486f6 100644 --- a/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp @@ -1,96 +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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "litImageTester.h" #include "boost/filesystem.hpp" -#include "boost/algorithm/string.hpp" - -#include "itkImage.h" #include "rttbITKIOHelper.h" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int BioModelCalcParameterMapsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string bioModelCalcExecutable; std::string doseFilename; std::string doseFilenameLoadStyle; std::string modelName; std::string modelParameterMaps; std::string modelParameterMapsLoadStyle; std::string referenceFilename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 7) { bioModelCalcExecutable = argv[1]; doseFilename = argv[2]; doseFilenameLoadStyle = argv[3]; modelName = argv[4]; modelParameterMaps = argv[5]; modelParameterMapsLoadStyle = argv[6]; referenceFilename = argv[7]; } std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; std::string defaultOutputFilename = "bioModelParameterMapOutput.nrrd"; std::string baseCommand = bioModelCalcExeWithPath; baseCommand += " -d \"" + doseFilename + "\""; baseCommand += " -t " + doseFilenameLoadStyle; baseCommand += " -o " + defaultOutputFilename; baseCommand += " -m " + modelName; baseCommand += " -a " + modelParameterMaps; baseCommand += " -u " + modelParameterMapsLoadStyle; std::string defaultDoseStatisticsCommand = baseCommand; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); // Check result against reference typedef ::itk::Image TestImageType; TestImageType::Pointer referenceImage = io::itk::readITKDoubleImage(referenceFilename); TestImageType::Pointer outputImage = io::itk::readITKDoubleImage(defaultOutputFilename); lit::ImageTester tester; tester.setExpectedImage(referenceImage); tester.setActualImage(outputImage); tester.setCheckThreshold(0.0); CHECK_TESTER(tester); CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp b/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp index a21bbda..0b7f29f 100644 --- a/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp @@ -1,124 +1,122 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "litImageTester.h" #include "boost/filesystem.hpp" -#include "itkImage.h" - #include "rttbITKIOHelper.h" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int BioModelCalcSimpleTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string bioModelCalcExecutable; std::string doseFilename; std::string doseFilenameLoadStyle; std::string modelName; std::string modelArguments; std::string referenceFilename; std::string referenceWithNFractionsFilename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 7) { bioModelCalcExecutable = argv[1]; doseFilename = argv[2]; doseFilenameLoadStyle = argv[3]; modelName = argv[4]; modelArguments = argv[5]; referenceFilename = argv[6]; referenceWithNFractionsFilename = argv[7]; } std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; std::string defaultOutputFilename = "bioModelOutput.nrrd"; std::string baseCommand = bioModelCalcExeWithPath; baseCommand += " -d \"" + doseFilename + "\""; baseCommand += " -t " + doseFilenameLoadStyle; baseCommand += " -o " + defaultOutputFilename; baseCommand += " -m " + modelName; baseCommand += " -p " + modelArguments; std::string defaultDoseStatisticsCommand = baseCommand; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); std::string defaultOutputWithNFractionsFilename = "bioModelWithNFractionsOutput.nrrd"; std::string baseCommandWithNFractions = bioModelCalcExeWithPath; baseCommandWithNFractions += " -d \"" + doseFilename + "\""; baseCommandWithNFractions += " -t " + doseFilenameLoadStyle; baseCommandWithNFractions += " -o " + defaultOutputWithNFractionsFilename; baseCommandWithNFractions += " -m " + modelName; baseCommandWithNFractions += " -p " + modelArguments; baseCommandWithNFractions += " -f 2"; std::cout << "Command line call: " + baseCommandWithNFractions << std::endl; CHECK_EQUAL(system(baseCommandWithNFractions.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); // Check result against reference typedef ::itk::Image TestImageType; TestImageType::Pointer referenceImage = io::itk::readITKDoubleImage(referenceFilename); TestImageType::Pointer outputImage = io::itk::readITKDoubleImage(defaultOutputFilename); lit::ImageTester tester; tester.setExpectedImage(referenceImage); tester.setActualImage(outputImage); tester.setCheckThreshold(0.0); CHECK_TESTER(tester); CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputWithNFractionsFilename), true); // Check result against reference TestImageType::Pointer referenceImageNFractions = io::itk::readITKDoubleImage(referenceWithNFractionsFilename); TestImageType::Pointer outputImageNFractions = io::itk::readITKDoubleImage(defaultOutputWithNFractionsFilename); lit::ImageTester testerWithNFractions; testerWithNFractions.setExpectedImage(referenceImageNFractions); testerWithNFractions.setActualImage(outputImageNFractions); testerWithNFractions.setCheckThreshold(0.0); CHECK_TESTER(testerWithNFractions); CHECK_EQUAL(std::remove(defaultOutputWithNFractionsFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcTests.cpp b/testing/apps/BioModelCalc/BioModelCalcTests.cpp index 80c298d..1b751fe 100644 --- a/testing/apps/BioModelCalc/BioModelCalcTests.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcTests.cpp @@ -1,65 +1,63 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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" -#include "RTToolboxConfigure.h" - namespace rttb { namespace testing { const char* _callingAppPath = nullptr; void registerTests() { LIT_REGISTER_TEST(BioModelCalcInvalidParametersTest); LIT_REGISTER_TEST(BioModelCalcSimpleTest); LIT_REGISTER_TEST(BioModelCalcParameterMapsTest); } } //namespace testing } //namespace map int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); if (argc > 0) { rttb::testing::_callingAppPath = argv[0]; } try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; } diff --git a/testing/apps/DoseAcc/DoseAccNeutralWeightTest.cpp b/testing/apps/DoseAcc/DoseAccNeutralWeightTest.cpp index b08592d..469e32b 100644 --- a/testing/apps/DoseAcc/DoseAccNeutralWeightTest.cpp +++ b/testing/apps/DoseAcc/DoseAccNeutralWeightTest.cpp @@ -1,102 +1,100 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "litImageTester.h" #include "boost/filesystem.hpp" -#include "itkImage.h" - #include "rttbITKIOHelper.h" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int DoseAccNeutralWeightTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseAccExecutable; std::string doseFilename; std::string referenceFilename; std::string reference2Filename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 4) { doseAccExecutable = argv[1]; doseFilename = argv[2]; referenceFilename = argv[3]; reference2Filename = argv[4]; } std::string doseAccExeWithPath = callingPath.parent_path().string() + "/" + doseAccExecutable; const std::string defaultOutputAddFilename = "doseAccAddOutput.nrrd"; const std::string defaultOutputMultFilename = "doseAccMultOutput.nrrd"; std::string baseCommand = doseAccExeWithPath; baseCommand += " -d \"" + doseFilename + "\""; baseCommand += " -e \"" + doseFilename + "\""; std::string defaultDoseAccAddCommand = baseCommand + " -o " + defaultOutputAddFilename + " --weight1 0.0"; std::cout << "Command line call: " + defaultDoseAccAddCommand << std::endl; CHECK_EQUAL(system(defaultDoseAccAddCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputAddFilename), true); std::string defaultDoseAccMultCommand = baseCommand + " -o " + defaultOutputMultFilename + " --operator \"*\""; std::cout << "Command line call: " + defaultDoseAccMultCommand << std::endl; CHECK_EQUAL(system(defaultDoseAccMultCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputMultFilename), true); // Check result against reference typedef ::itk::Image TestImageType; TestImageType::Pointer referenceAddImage = io::itk::readITKDoubleImage(referenceFilename); TestImageType::Pointer outputAddImage = io::itk::readITKDoubleImage(defaultOutputAddFilename); lit::ImageTester tester; tester.setExpectedImage(referenceAddImage); tester.setActualImage(outputAddImage); tester.setCheckThreshold(1e-5); CHECK_TESTER(tester); TestImageType::Pointer referenceMultImage = io::itk::readITKDoubleImage(reference2Filename); TestImageType::Pointer outputMultImage = io::itk::readITKDoubleImage(defaultOutputMultFilename); tester.setExpectedImage(referenceMultImage); tester.setActualImage(outputMultImage); tester.setCheckThreshold(1e-5); CHECK_TESTER(tester); CHECK_EQUAL(std::remove(defaultOutputAddFilename.c_str()), 0); CHECK_EQUAL(std::remove(defaultOutputMultFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseAcc/DoseAccSimpleTest.cpp b/testing/apps/DoseAcc/DoseAccSimpleTest.cpp index 6fb8af3..c111483 100644 --- a/testing/apps/DoseAcc/DoseAccSimpleTest.cpp +++ b/testing/apps/DoseAcc/DoseAccSimpleTest.cpp @@ -1,86 +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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "litImageTester.h" #include "boost/filesystem.hpp" -#include "itkImage.h" - #include "rttbITKIOHelper.h" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int DoseAccSimpleTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseAccExecutable; std::string dose1Filename; std::string dose2Filename; std::string referenceFilename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 4) { doseAccExecutable = argv[1]; dose1Filename = argv[2]; dose2Filename = argv[3]; referenceFilename = argv[4]; } std::string doseAccExeWithPath = callingPath.parent_path().string() + "/" + doseAccExecutable; std::string defaultOutputFilename = "doseAccOutput.nrrd"; std::string baseCommand = doseAccExeWithPath; baseCommand += " -d \"" + dose1Filename + "\""; baseCommand += " -e \"" + dose2Filename + "\""; baseCommand += " -o " + defaultOutputFilename; std::string defaultDoseAccCommand = baseCommand + " --weight1 2.0"; std::cout << "Command line call: " + defaultDoseAccCommand << std::endl; CHECK_EQUAL(system(defaultDoseAccCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); // Check result against reference typedef ::itk::Image TestImageType; TestImageType::Pointer referenceImage = io::itk::readITKDoubleImage(referenceFilename); TestImageType::Pointer outputImage = io::itk::readITKDoubleImage(defaultOutputFilename); lit::ImageTester tester; tester.setExpectedImage(referenceImage); tester.setActualImage(outputImage); tester.setCheckThreshold(0.0); CHECK_TESTER(tester); CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseAcc/DoseAccTests.cpp b/testing/apps/DoseAcc/DoseAccTests.cpp index 8b6e2cc..aa3bf4a 100644 --- a/testing/apps/DoseAcc/DoseAccTests.cpp +++ b/testing/apps/DoseAcc/DoseAccTests.cpp @@ -1,65 +1,63 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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" -#include "RTToolboxConfigure.h" - namespace rttb { namespace testing { const char* _callingAppPath = nullptr; void registerTests() { LIT_REGISTER_TEST(DoseAccInvalidParametersTest); LIT_REGISTER_TEST(DoseAccSimpleTest); LIT_REGISTER_TEST(DoseAccNeutralWeightTest); } } //namespace testing } //namespace map int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); if (argc > 0) { rttb::testing::_callingAppPath = argv[0]; } try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; } diff --git a/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp b/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp index 12a7f45..0e701f3 100644 --- a/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp +++ b/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp @@ -1,131 +1,129 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "rttbDoseStatisticsXMLReader.h" #include "rttbDVHXMLFileReader.h" #include "../../io/other/CompareDoseStatistic.h" #include "../../io/other/CompareDVH.h" -#include "litCheckMacros.h" - #include "boost/filesystem.hpp" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int DoseToolDicomDoseTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseToolExecutable; std::string doseFilename; std::string structFilename; std::string structName; std::string referenceXMLFilename; std::string referenceDVHXMLFilename; std::string referenceXMLComplexFilename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 7) { doseToolExecutable = argv[1]; doseFilename = argv[2]; structFilename = argv[3]; structName = argv[4]; referenceXMLFilename = argv[5]; referenceDVHXMLFilename = argv[6]; referenceXMLComplexFilename = argv[7]; } std::string doseToolExeWithPath = callingPath.parent_path().string() + "/" + doseToolExecutable; std::string defaultOutputFilename = "dicomDoseOutput.xml"; std::string defaultDVHOutputFilename = "dicomDoseDVHOutput.xml"; std::string complexOutputFilename = "dicomDoseOutputComplex.xml"; std::string baseCommand = doseToolExeWithPath; baseCommand += " -d \"" + doseFilename + "\""; baseCommand += " -s \"" + structFilename + "\""; if (structName != "") { baseCommand += " -n " + structName; } else { baseCommand += " -u itk "; } std::string defaultDoseStatisticsCommand = baseCommand + " -y " + defaultOutputFilename; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); std::string defaultDoseStatisticsAndDVHCommand = defaultDoseStatisticsCommand + " -z " + defaultDVHOutputFilename; std::cout << "Command line call: " + defaultDoseStatisticsAndDVHCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsAndDVHCommand.c_str()), 0); std::string complexDoseStatisticsCommand = baseCommand + " -y " + complexOutputFilename; //prescribed dose is 14 Gy complexDoseStatisticsCommand += " -f -p 14"; std::cout << "Command line call: " + complexDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(complexDoseStatisticsCommand.c_str()), 0); //check if file exists CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(complexOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultDVHOutputFilename), true); //check if file has dose statistics that are same than these in than reference file io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); auto doseStatisticsDefaultExpected = readerDefaultExpected.generateDoseStatistic(); io::other::DoseStatisticsXMLReader readerDefaultActual(defaultOutputFilename); auto doseStatisticsDefaultActual = readerDefaultActual.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsDefaultExpected, doseStatisticsDefaultActual)); io::other::DoseStatisticsXMLReader readerComplexExpected(complexOutputFilename); auto doseStatisticsComplexExpected = readerComplexExpected.generateDoseStatistic(); io::other::DoseStatisticsXMLReader readerComplexActual(referenceXMLComplexFilename); auto doseStatisticsComplexActual = readerComplexActual.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsComplexExpected, doseStatisticsComplexActual)); //check DVH files io::other::DVHXMLFileReader xmlDVHDefaultReaderActual(defaultDVHOutputFilename); core::DVH::Pointer defaultDVHActual = xmlDVHDefaultReaderActual.generateDVH(); io::other::DVHXMLFileReader xmlDVHDefaultReaderExpected(referenceDVHXMLFilename); core::DVH::Pointer defaultDVHExpected = xmlDVHDefaultReaderExpected.generateDVH(); CHECK(checkEqualDVH(defaultDVHActual, defaultDVHExpected)); //delete file again CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(defaultDVHOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(complexOutputFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseTool/DoseToolRegexTest.cpp b/testing/apps/DoseTool/DoseToolRegexTest.cpp index 6981dc0..c021494 100644 --- a/testing/apps/DoseTool/DoseToolRegexTest.cpp +++ b/testing/apps/DoseTool/DoseToolRegexTest.cpp @@ -1,113 +1,111 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ #include "rttbDoseStatisticsXMLReader.h" #include "../../io/other/CompareDoseStatistic.h" -#include "litCheckMacros.h" - #include "boost/filesystem.hpp" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int DoseToolRegexTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseToolExecutable; std::string doseFilename; std::string doseLoadStyle; std::string structFilename; std::string structLoadStyle; std::string structName; std::string referenceXMLFilename; std::string referenceXMLFilename2; boost::filesystem::path callingPath(_callingAppPath); if (argc > 8) { doseToolExecutable = argv[1]; doseFilename = argv[2]; doseLoadStyle = argv[3]; structFilename = argv[4]; structLoadStyle = argv[5]; structName = argv[6]; referenceXMLFilename = argv[7]; referenceXMLFilename2 = argv[8]; } std::string doseToolExeWithPath = callingPath.parent_path().string() + "/" + doseToolExecutable; std::string defaultOutputFilename = "regexOutput.xml"; std::string defaultExpectedOutputFilename = "regexOutput_Nodes.xml"; std::string defaultExpectedOutputFilename2 = "regexOutput_Heart.xml"; std::string baseCommand = doseToolExeWithPath; baseCommand += " -d \"" + doseFilename + "\""; baseCommand += " -t " + doseLoadStyle; baseCommand += " -s \"" + structFilename + "\""; baseCommand += " -u " + structLoadStyle; baseCommand += " -n \"" + structName + "\""; baseCommand += " -y " + defaultOutputFilename; std::cout << "Command line call: " + baseCommand << std::endl; CHECK_EQUAL(system(baseCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename), false); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename2), false); CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); std::string defaultDoseStatisticsCommand = baseCommand + " -m"; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); //check if two file were written CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename2), true); //check if file has dose statistics that are same than these in than reference file io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); auto doseStatisticsDefaultExpected = readerDefaultExpected.generateDoseStatistic(); io::other::DoseStatisticsXMLReader readerDefaultActual(defaultExpectedOutputFilename); auto doseStatisticsDefaultActual = readerDefaultActual.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsDefaultExpected, doseStatisticsDefaultActual)); io::other::DoseStatisticsXMLReader readerDefaultExpected2(referenceXMLFilename2); auto doseStatisticsDefaultExpected2 = readerDefaultExpected2.generateDoseStatistic(); io::other::DoseStatisticsXMLReader readerDefaultActual2(defaultExpectedOutputFilename2); auto doseStatisticsDefaultActual2 = readerDefaultActual2.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsDefaultExpected2, doseStatisticsDefaultActual2)); //delete file again CHECK_EQUAL(std::remove(defaultExpectedOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(defaultExpectedOutputFilename2.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseTool/DoseToolTests.cpp b/testing/apps/DoseTool/DoseToolTests.cpp index c3dc74a..d06ac64 100644 --- a/testing/apps/DoseTool/DoseToolTests.cpp +++ b/testing/apps/DoseTool/DoseToolTests.cpp @@ -1,67 +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. // //------------------------------------------------------------------------ // 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" -#include "RTToolboxConfigure.h" - namespace rttb { namespace testing { const char* _callingAppPath = nullptr; void registerTests() { LIT_REGISTER_TEST(DoseToolInvalidParametersTest); LIT_REGISTER_TEST(DoseToolDicomDoseTest); LIT_REGISTER_TEST(DoseToolITKDoseTest); LIT_REGISTER_TEST(DoseToolRegexTest); LIT_REGISTER_TEST(DoseToolDVHTest); } } //namespace testing } //namespace map int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); if (argc > 0) { rttb::testing::_callingAppPath = argv[0]; } try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; } diff --git a/testing/apps/VoxelizerTool/VoxelizerToolDifferentCommandsTest.cpp b/testing/apps/VoxelizerTool/VoxelizerToolDifferentCommandsTest.cpp index c7f3cc3..0740455 100644 --- a/testing/apps/VoxelizerTool/VoxelizerToolDifferentCommandsTest.cpp +++ b/testing/apps/VoxelizerTool/VoxelizerToolDifferentCommandsTest.cpp @@ -1,130 +1,129 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include "litCheckMacros.h" -#include -#include #include "itkImage.h" #include "itkImageFileReader.h" -#include +#include "litCheckMacros.h" + +#include /*! @brief VoxelizerToolTest3. Test the output, multipleStructs and the booleanVoxelization parameter. */ namespace rttb { namespace testing { //path to the current running directory. VoxelizerTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int VoxelizerToolDifferentCommandsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef itk::Image< double, 3 > ImageType; typedef itk::ImageFileReader ReaderType; std::string voxelizerToolExe; std::string tempDirectory; std::string structFile; std::string referenceFile; if (argc > 4) { voxelizerToolExe = argv[1]; tempDirectory = argv[2]; structFile = argv[3]; referenceFile = argv[4]; } std::vector commands; commands.push_back("\"Niere.*\" -m -o Test.hdr"); commands.push_back("\"Rueckenmark\" -o Boolean.hdr -z"); std::vector filenames; filenames.push_back("Test_Niere li"); filenames.push_back("Test_Niere re"); filenames.push_back("Boolean"); std::vector > voxelsToTestInside; std::vector > voxelsToTestOutside; voxelsToTestInside.push_back(std::make_pair(ImageType::IndexType{ 48, 31, 18 }, 1.0)); //Niere li inside voxelsToTestOutside.push_back(std::make_pair(ImageType::IndexType{ 19, 31, 18 }, 0.0)); //Niere li outside voxelsToTestInside.push_back(std::make_pair(ImageType::IndexType{ 19, 31, 18 }, 1.0)); //Niere re inside voxelsToTestOutside.push_back(std::make_pair(ImageType::IndexType{ 48, 31, 18 }, 0.0)); //Niere re outside voxelsToTestInside.push_back(std::make_pair(ImageType::IndexType{ 35, 32, 30 }, 1.0)); //Rueckenmark inside voxelsToTestOutside.push_back(std::make_pair(ImageType::IndexType{ 35, 30, 23 }, 0.0)); //Rueckenmark outside boost::filesystem::path callingPath(_callingAppPath); std::string voxelizerToolExeWithPath = callingPath.parent_path().string() + "/" + voxelizerToolExe; std::string baseCommand = voxelizerToolExeWithPath; baseCommand += " -s \"" + structFile + "\""; baseCommand += " -r \"" + referenceFile + "\""; baseCommand += " -e "; for (size_t i = 0; i < commands.size(); i++) { std::string command = baseCommand + commands.at(i); int returnValue = system(command.c_str()); std::cout << "Command line call: " + command << std::endl; CHECK_EQUAL(returnValue, 0); } for (size_t i = 0; i < filenames.size(); i++) { const std::string HDRfileName = tempDirectory + "/" + filenames.at(i) + ".hdr"; boost::filesystem::path HDRFile(HDRfileName); const std::string IMGfileName = tempDirectory + "/" + filenames.at(i) + ".img"; boost::filesystem::path IMGFile(IMGfileName); CHECK_EQUAL(boost::filesystem::exists(HDRFile), true); CHECK_EQUAL(boost::filesystem::exists(IMGFile), true); //check voxel values if (boost::filesystem::exists(HDRFile)) { ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(HDRfileName); reader->Update(); ReaderType::OutputImageType::ConstPointer image = reader->GetOutput(); ImageType::PixelType voxelValueInside = image->GetPixel(voxelsToTestInside.at(i).first); ImageType::PixelType expectedVoxelValueInside = voxelsToTestInside.at(i).second; CHECK_EQUAL(voxelValueInside, expectedVoxelValueInside); ImageType::PixelType voxelValueOutside = image->GetPixel(voxelsToTestOutside.at(i).first); ImageType::PixelType expectedVoxelValueOutside = voxelsToTestOutside.at(i).second; CHECK_EQUAL(voxelValueOutside, expectedVoxelValueOutside); } if (boost::filesystem::exists(IMGFile)) { boost::filesystem::remove(IMGFile); } if (boost::filesystem::exists(HDRFile)) { boost::filesystem::remove(HDRFile); } } RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/apps/VoxelizerTool/VoxelizerToolIncorrectCommandsTest.cpp b/testing/apps/VoxelizerTool/VoxelizerToolIncorrectCommandsTest.cpp index 7b112d1..d2330c3 100644 --- a/testing/apps/VoxelizerTool/VoxelizerToolIncorrectCommandsTest.cpp +++ b/testing/apps/VoxelizerTool/VoxelizerToolIncorrectCommandsTest.cpp @@ -1,114 +1,114 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include #include "litCheckMacros.h" #include +#include /*! @brief VoxelizerToolTest4. Test incorrect commands with a wrong structfile, referencefile and a wrong struct. if the command return one, the program could not run to the end. return zero the command is correct */ namespace rttb { namespace testing { //path to the current running directory. VoxelizerTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int VoxelizerToolIncorrectCommandsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string voxelizerToolExe; std::string structFile; std::string invalidStructFile; std::string invalidReferenceFile; std::string referenceFile; std::string structureName; std::string invalidStructureName; if (argc > 7) { voxelizerToolExe = argv[1]; structFile = argv[2]; invalidStructFile = argv[3]; referenceFile = argv[4]; invalidReferenceFile = argv[5]; structureName = argv[6]; invalidStructureName = argv[7]; } boost::filesystem::path callingPath(_callingAppPath); std::string voxelizerToolExeWithPath = callingPath.parent_path().string() + "/" + voxelizerToolExe; std::string tooFewArgumentsCommand = voxelizerToolExeWithPath; tooFewArgumentsCommand += " -s " + invalidStructFile; tooFewArgumentsCommand += " -r " + referenceFile; std::cout << "Command line call: " + tooFewArgumentsCommand << std::endl; CHECK_EQUAL(system(tooFewArgumentsCommand.c_str()) != 0, true); tooFewArgumentsCommand = voxelizerToolExeWithPath; tooFewArgumentsCommand += " -s " + invalidStructFile; tooFewArgumentsCommand += " -e " + structureName; std::cout << "Command line call: " + tooFewArgumentsCommand << std::endl; CHECK_EQUAL(system(tooFewArgumentsCommand.c_str()) != 0, true); tooFewArgumentsCommand = voxelizerToolExeWithPath; std::cout << "Command line call: " + tooFewArgumentsCommand << std::endl; CHECK_EQUAL(system(tooFewArgumentsCommand.c_str()) != 0, true); std::string noOutputEndingCommand = voxelizerToolExeWithPath; noOutputEndingCommand += " -s " + invalidStructFile; noOutputEndingCommand += " -r " + referenceFile; noOutputEndingCommand += " -e " + structureName; noOutputEndingCommand += " -o bla"; std::cout << "Command line call: " + noOutputEndingCommand << std::endl; CHECK_EQUAL(system(noOutputEndingCommand.c_str()) != 0, true); std::string structCommand = voxelizerToolExeWithPath; structCommand += " -s " + invalidStructFile; structCommand += " -r " + referenceFile; structCommand += " -e " + structureName; std::cout << "Command line call: " + structCommand << std::endl; CHECK_EQUAL(system(structCommand.c_str()) != 0, true); std::string referenceCommand = voxelizerToolExeWithPath; referenceCommand += " -s " + structFile; referenceCommand += " -r " + invalidReferenceFile; referenceCommand += " -e " + structureName; std::cout << "Command line call: " + referenceCommand << std::endl; CHECK_EQUAL(system(referenceCommand.c_str()) != 0, true); std::string structureNameCommand = voxelizerToolExeWithPath; structureNameCommand += " -s " + structFile; structureNameCommand += " -r " + referenceFile; structureNameCommand += +" -e " + invalidStructureName; std::cout << "Command line call: " + structureNameCommand << std::endl; CHECK_EQUAL(system(structureNameCommand.c_str()), 0); std::string referenceLoadingStyleCommand = voxelizerToolExeWithPath; referenceLoadingStyleCommand += " -s " + structFile; referenceLoadingStyleCommand += " -r " + referenceFile; referenceLoadingStyleCommand += +" -e " + invalidStructureName; referenceLoadingStyleCommand += +" -y nonsense"; std::cout << "Command line call: " + referenceLoadingStyleCommand << std::endl; CHECK_EQUAL(system(referenceLoadingStyleCommand.c_str()) != 0, true); RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/apps/VoxelizerTool/VoxelizerToolVoxelValueTest.cpp b/testing/apps/VoxelizerTool/VoxelizerToolVoxelValueTest.cpp index 6a2a124..5f22315 100644 --- a/testing/apps/VoxelizerTool/VoxelizerToolVoxelValueTest.cpp +++ b/testing/apps/VoxelizerTool/VoxelizerToolVoxelValueTest.cpp @@ -1,127 +1,126 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include "litCheckMacros.h" -#include #include "itkImage.h" #include "itkImageFileReader.h" -#include +#include "litCheckMacros.h" #include +#include /*! @brief VoxelizerToolTest5. Search the coordinate at the Image and return the Voxel(Pixel) value. */ namespace rttb { namespace testing { //path to the current running directory. VoxelizerTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int VoxelizerToolVoxelValue(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef itk::Image< double, 3 > ImageType; typedef itk::ImageFileReader ReaderType; std::string voxelizerToolExe; std::string tempDirectory; std::string structFile; std::string referenceFile; std::string structName; if (argc > 5) { voxelizerToolExe = argv[1]; tempDirectory = argv[2]; structFile = argv[3]; referenceFile = argv[4]; structName = argv[5]; } boost::filesystem::path callingPath(_callingAppPath); std::string voxelizerToolExeWithPath = callingPath.parent_path().string() + "/" + voxelizerToolExe; std::string command = voxelizerToolExeWithPath; command += " -s \"" + structFile + "\""; command += " -r \"" + referenceFile + "\""; command += " -e " + structName; command += " -o testOutputVoxelValue.hdr"; int returnValue = system(command.c_str()); CHECK_EQUAL(returnValue, 0); //image values taken in Mevislab //Index inside ImageType::IndexType voxelInside1 = {{20, 30, 30}}; ImageType::IndexType voxelInside2 = {{30, 10, 40}}; //Outside index ImageType::IndexType voxelOutside1 = {{40, 30, 30}}; ImageType::IndexType voxelOutside2 = {{10, 40, 30}}; //Border index ImageType::IndexType voxelBorder1 = {{12, 23, 27}}; ImageType::IndexType voxelBorder2 = {{34, 21, 31}}; std::vector voxelIndices = boost::assign::list_of(voxelInside1)(voxelInside2)( voxelOutside1)( voxelOutside2)(voxelBorder1)(voxelBorder2); std::vector expectedVoxelValues = boost::assign::list_of(1.0)(1.0)(0.0)(0.0)( 0.265865)(0.819613); std::string filenameHDRWithVoxelization = tempDirectory + "/testOutputVoxelValue.hdr"; std::string filenameIMGWithVoxelization = tempDirectory + "/testOutputVoxelValue.img"; CHECK(boost::filesystem::exists(filenameHDRWithVoxelization)); CHECK(boost::filesystem::exists(filenameIMGWithVoxelization)); if (boost::filesystem::exists(filenameHDRWithVoxelization)) { ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(filenameHDRWithVoxelization); reader->Update(); ReaderType::OutputImageType::ConstPointer image = reader->GetOutput(); for (size_t i = 0; i < voxelIndices.size(); i++) { ImageType::PixelType voxelValue = image->GetPixel(voxelIndices.at(i)); ImageType::PixelType expectedVoxelValue = expectedVoxelValues.at(i); if (expectedVoxelValue == 0.0 || expectedVoxelValue == 1.0) { CHECK_EQUAL(voxelValue, expectedVoxelValue); } else { CHECK_CLOSE(voxelValue, expectedVoxelValue, 1e-4); } } boost::filesystem::remove(filenameHDRWithVoxelization); if (boost::filesystem::exists(filenameIMGWithVoxelization)) { boost::filesystem::remove(filenameIMGWithVoxelization); } } RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerAllStructsTest.cpp b/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerAllStructsTest.cpp index 3167347..6dd728a 100644 --- a/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerAllStructsTest.cpp +++ b/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerAllStructsTest.cpp @@ -1,98 +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. // //------------------------------------------------------------------------ -#include #include "litCheckMacros.h" + #include -#include +#include /*! @brief VoxelizerToolTest. Tests a selection of structs. */ namespace rttb { namespace testing { //path to the current running directory. VoxelizerTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int VoxelizerToolVoxelizerAllStructsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string voxelizerToolExe; std::string tempDirectory; std::string structFile; std::string referenceFile; if (argc > 4) { voxelizerToolExe = argv[1]; tempDirectory = argv[2]; structFile = argv[3]; referenceFile = argv[4]; } boost::filesystem::path callingPath(_callingAppPath); std::string voxelizerToolExeWithPath = callingPath.parent_path().string() + "/" + voxelizerToolExe; std::vector structNames; structNames.push_back("Niere.*"); structNames.push_back("Magen/DD"); structNames.push_back("PTV"); std::string baseCommand = voxelizerToolExeWithPath; baseCommand += " -s \"" + structFile + "\""; baseCommand += " -r \"" + referenceFile + "\""; baseCommand += " -o outputAllStructs.hdr"; baseCommand += " -e \""; for (size_t i = 0; i < structNames.size(); i++) { std::string command = baseCommand + structNames.at(i) + "\""; std::cout << "Command line call: " + command << std::endl; int returnValue = system(command.c_str()); CHECK_EQUAL(returnValue, 0); boost::filesystem::path HDRFile(tempDirectory); HDRFile /= "outputAllStructs.hdr"; boost::filesystem::path IMGFile(tempDirectory); IMGFile /= "outputAllStructs.img"; CHECK_EQUAL( boost::filesystem::exists(HDRFile), true); CHECK_EQUAL( boost::filesystem::exists(IMGFile), true); if (boost::filesystem::exists(IMGFile)) { boost::filesystem::remove(IMGFile); } if (boost::filesystem::exists(HDRFile)) { boost::filesystem::remove(HDRFile); } } RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerStructTest.cpp b/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerStructTest.cpp index a42560c..f1490b6 100644 --- a/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerStructTest.cpp +++ b/testing/apps/VoxelizerTool/VoxelizerToolVoxelizerStructTest.cpp @@ -1,98 +1,99 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include #include "litCheckMacros.h" + #include +#include /*! @brief VoxelizerToolTest. Tests a struct with multiple files and a single file */ namespace rttb { namespace testing { //path to the current running directory. VoxelizerTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int VoxelizerToolVoxelizerStructTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string voxelizerToolExe; std::string tempDirectory; std::string structFile; std::string referenceFile; boost::filesystem::path HDRFile(tempDirectory); HDRFile /= "outputSingleStruct.hdr"; boost::filesystem::path IMGFile(tempDirectory); IMGFile /= "outputSingleStruct.img"; if (argc > 4) { voxelizerToolExe = argv[1]; tempDirectory = argv[2]; structFile = argv[3]; referenceFile = argv[4]; } boost::filesystem::path callingPath(_callingAppPath); std::string voxelizerToolExeWithPath = callingPath.parent_path().string() + "/" + voxelizerToolExe; std::string structName = "Heart"; std::string baseCommand = voxelizerToolExeWithPath; baseCommand += " -s \"" + structFile + "\""; baseCommand += " -r \"" + referenceFile + "\""; baseCommand += " -o outputSingleStruct.hdr"; baseCommand += " -y itkDicom"; baseCommand += " -e \""; std::string command = baseCommand + structName + "\""; std::cout << "Command line call: " + command << std::endl; int returnValue = system(command.c_str()); CHECK_EQUAL(returnValue, 0); CHECK_EQUAL(boost::filesystem::exists(HDRFile), true); CHECK_EQUAL(boost::filesystem::exists(IMGFile), true); baseCommand = voxelizerToolExeWithPath; baseCommand += " -s \"" + structFile + "\""; baseCommand += " -r \"" + HDRFile.string() + "\""; baseCommand += " -o outputSingleStruct.hdr"; baseCommand += " -y itk"; baseCommand += " -e \""; command = baseCommand + structName + "\""; std::cout << "Command line call: " + command << std::endl; returnValue = system(command.c_str()); CHECK_EQUAL(returnValue, 0); if (boost::filesystem::exists(IMGFile)) { boost::filesystem::remove(IMGFile); } if (boost::filesystem::exists(HDRFile)) { boost::filesystem::remove(HDRFile); } RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/core/CreateTestStructure.cpp b/testing/core/CreateTestStructure.cpp index d310ac4..dc622d2 100644 --- a/testing/core/CreateTestStructure.cpp +++ b/testing/core/CreateTestStructure.cpp @@ -1,681 +1,676 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests -#include - #include "CreateTestStructure.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" -#include "rttbInvalidDoseException.h" namespace rttb { namespace testing { CreateTestStructure::~CreateTestStructure() {} CreateTestStructure::CreateTestStructure(const core::GeometricInfo& aGeoInfo) { _geoInfo = aGeoInfo; } PolygonType CreateTestStructure::createPolygonLeftUpper(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); polygon.push_back(p1); std::cout << "(" << p1.x() << "," << p1.y() << "," << p1.z() << ")" << "; "; } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonCenter(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); WorldCoordinate3D p; p(0) = p1.x() ; p(1) = p1.y() ; //This can be done directly for x/y coordinates, but not for z. Thus, we do it in this function. p(2) = p1.z() - _geoInfo.getSpacing().z() / 2; polygon.push_back(p); } return polygon; } PolygonType CreateTestStructure::createPolygonCenterOnPlaneCenter(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; DoubleVoxelGridIndex3D indexDouble = DoubleVoxelGridIndex3D((aVoxelVector.at(i)).x(), (aVoxelVector.at(i)).y(), sliceNumber); WorldCoordinate3D p1; _geoInfo.geometryCoordinateToWorldCoordinate(indexDouble, p1); polygon.push_back(p1); } return polygon; } PolygonType CreateTestStructure::createPolygonBetweenUpperLeftAndCenter( std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D p; p(0) = p1.x() + delta.x() / 4; p(1) = p1.y() + delta.y() / 4; p(2) = p1.z(); polygon.push_back(p); std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonBetweenLowerRightAndCenter( std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D p; p(0) = p1.x() + delta.x() * 0.75; p(1) = p1.y() + delta.y() * 0.75; p(2) = p1.z(); polygon.push_back(p); std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonLeftEdgeMiddle(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D p; p(0) = p1.x(); p(1) = p1.y() + delta.y() * 0.5; p(2) = p1.z(); polygon.push_back(p); std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonUpperCenter(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D p; p(0) = p1.x() + delta.x() * 0.5; p(1) = p1.y(); p(2) = p1.z(); polygon.push_back(p); std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonIntermediatePoints(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; for (size_t i = 0; i < aVoxelVector.size(); i++) { VoxelGridIndex3D voxelIndex; VoxelGridIndex3D voxelIndex2; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; if (i < (aVoxelVector.size() - 1)) { voxelIndex2(0) = (aVoxelVector.at(i + 1)).x(); voxelIndex2(1) = (aVoxelVector.at(i + 1)).y(); voxelIndex2(2) = sliceNumber; } else { voxelIndex2(0) = (aVoxelVector.at(0)).x(); voxelIndex2(1) = (aVoxelVector.at(0)).y(); voxelIndex2(2) = sliceNumber; } WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D p2; _geoInfo.indexToWorldCoordinate(voxelIndex2, p2); SpacingVectorType3D delta2 = _geoInfo.getSpacing(); WorldCoordinate3D wp1; wp1(0) = p1.x() + delta.x() * 0.75; wp1(1) = p1.y() + delta.y() * 0.75; wp1(2) = p1.z(); WorldCoordinate3D wp2; wp2(0) = p2.x() + delta.x() * 0.75; wp2(1) = p2.y() + delta.y() * 0.75; wp2(2) = p2.z(); polygon.push_back(wp1); double diffX = (wp2.x() - wp1.x()) / 1000.0; double diffY = (wp2.y() - wp1.y()) / 1000.0; WorldCoordinate3D wp_intermediate; wp_intermediate(0) = 0; wp_intermediate(1) = 0; for (int j = 0; j < 1000; j++) { wp_intermediate(0) = wp1.x() + j * diffX; wp_intermediate(1) = wp1.y() + j * diffY; polygon.push_back(wp_intermediate); } } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createPolygonCircle(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; if (aVoxelVector.size() > 0) { unsigned int i = 0; VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D wp1; wp1(0) = p1.x(); wp1(1) = p1.y(); wp1(2) = p1.z(); WorldCoordinate3D wp_intermediate; wp_intermediate(0) = 0; wp_intermediate(1) = 0; wp_intermediate(2) = p1.z(); double radius = 2 * delta.x(); double frac_radius = (radius * 0.001); double correct_y = (delta.x() / delta.y()); for (unsigned int j = 0; j <= 1000; j++) { double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); wp_intermediate(0) = wp1.x() + frac_radius * j; wp_intermediate(1) = wp1.y() - (y_offset * correct_y); polygon.push_back(wp_intermediate); } for (unsigned int j = 1000; j <= 1000; j--) { double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); wp_intermediate(0) = wp1.x() + frac_radius * j; wp_intermediate(1) = wp1.y() + (y_offset * correct_y); polygon.push_back(wp_intermediate); } for (unsigned int j = 0; j <= 1000; j++) { double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); wp_intermediate(0) = wp1.x() - frac_radius * j; wp_intermediate(1) = wp1.y() + y_offset * correct_y; polygon.push_back(wp_intermediate); } for (unsigned int j = 1000; j <= 1000; j--) { double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); wp_intermediate(0) = wp1.x() + frac_radius * j; wp_intermediate(1) = wp1.y() + (y_offset * correct_y); polygon.push_back(wp_intermediate); } } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createStructureSeveralSectionsInsideOneVoxelA( std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; if (aVoxelVector.size() > 0) { int i = 0; VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D wp1; wp1(0) = p1.x(); wp1(1) = p1.y(); wp1(2) = p1.z(); WorldCoordinate3D wp_intermediate; wp_intermediate(0) = 0; wp_intermediate(1) = 0; wp_intermediate(2) = p1.z(); wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); polygon.push_back(wp_intermediate); } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createStructureSelfTouchingA(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; if (aVoxelVector.size() > 0) { int i = 0; VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D wp1; wp1(0) = p1.x(); wp1(1) = p1.y(); wp1(2) = p1.z(); WorldCoordinate3D wp_intermediate; wp_intermediate(0) = 0; wp_intermediate(1) = 0; wp_intermediate(2) = p1.z(); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y(); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); } std::cout << std::endl; return polygon; } PolygonType CreateTestStructure::createStructureSelfTouchingB(std::vector aVoxelVector, GridIndexType sliceNumber) { PolygonType polygon; if (aVoxelVector.size() > 0) { int i = 0; VoxelGridIndex3D voxelIndex; voxelIndex(0) = (aVoxelVector.at(i)).x(); voxelIndex(1) = (aVoxelVector.at(i)).y(); voxelIndex(2) = sliceNumber; WorldCoordinate3D p1; _geoInfo.indexToWorldCoordinate(voxelIndex, p1); SpacingVectorType3D delta = _geoInfo.getSpacing(); WorldCoordinate3D wp1; wp1(0) = p1.x(); wp1(1) = p1.y(); wp1(2) = p1.z(); WorldCoordinate3D wp_intermediate; wp_intermediate(0) = 0; wp_intermediate(1) = 0; wp_intermediate(2) = p1.z(); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y(); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); polygon.push_back(wp_intermediate); wp_intermediate(0) = wp1.x(); wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); polygon.push_back(wp_intermediate); } std::cout << std::endl; return polygon; } }//testing }//rttb diff --git a/testing/core/DVHCalculatorTest.cpp b/testing/core/DVHCalculatorTest.cpp index 53f1d7f..56408d8 100644 --- a/testing/core/DVHCalculatorTest.cpp +++ b/testing/core/DVHCalculatorTest.cpp @@ -1,148 +1,145 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests -#include -#include - +#include "DummyDoseAccessor.h" +#include "DummyMaskAccessor.h" #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbDVHCalculator.h" -#include "rttbGenericMaskedDoseIterator.h" -#include "rttbGeometricInfo.h" #include "rttbGenericDoseIterator.h" -#include "rttbNullPointerException.h" +#include "rttbGenericMaskedDoseIterator.h" #include "rttbInvalidParameterException.h" -#include "DummyDoseAccessor.h" -#include "DummyMaskAccessor.h" +#include "rttbNullPointerException.h" + +#include namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::DVHCalculator::DoseIteratorPointer DoseIteratorPointer; typedef core::DVHCalculator::MaskedDoseIteratorPointer MaskedDoseIteratorPointer; /*!@brief DVHTest - test the API of DVH 1) test constructors (values as expected?) */ int DVHCalculatorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //create null pointer to DoseIterator DoseIteratorPointer spDoseIteratorNull; const IDType structureID = "myStructure"; const IDType doseIDNull = "myDose"; //1) test constructors (values as expected?) CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIteratorNull, structureID, doseIDNull), core::NullPointerException); //create dummy DoseAccessor boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); //create corresponding DoseIterator boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); const IDType doseID = spDoseAccessor->getUID(); CHECK_NO_THROW(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID)); CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, -1), core::InvalidParameterException); int numBins = 21; DoseTypeGy binSize = 0; DoseStatisticType maximum = 0; std::vector::const_iterator doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (maximum < *doseIt) { maximum = *doseIt; } ++doseIt; } binSize = maximum * 1.5 / numBins; CHECK_NO_THROW(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, binSize, numBins)); CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, 0, 0), core::InvalidParameterException);//aNumberOfBins must be >=0 core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, binSize, 1); CHECK_THROW_EXPLICIT(myDVHCalc.generateDVH(), core::InvalidParameterException);//_numberOfBins must be > max(aDoseIterator)/aDeltaD! //generateDVH (only test basic functionality here and test it in RTTBDicomIOTests and RTTBITKIOTests) //create dummy DoseAccessor with values 0 to check if _deltaD is set to 0.1 std::vector zeros(1000, 0); core::GeometricInfo geoInfo; geoInfo.setNumColumns(10); geoInfo.setNumRows(10); geoInfo.setNumSlices(10); geoInfo.setSpacing({1.0, 1.0, 1.0}); boost::shared_ptr spTestDoseAccessorZeros = boost::make_shared(zeros, geoInfo); DoseAccessorPointer spDoseAccessorZeros(spTestDoseAccessorZeros); boost::shared_ptr spTestDoseIteratorZeros = boost::make_shared(spDoseAccessorZeros); DoseIteratorPointer spDoseIteratorZeros(spTestDoseIteratorZeros); CHECK_NO_THROW(core::DVHCalculator myDVHCalc2(spDoseIteratorZeros, structureID, doseID, 0, numBins)); core::DVHCalculator myDVHCalc2(spDoseIteratorZeros, structureID, doseID, 0, numBins); core::DVH::Pointer dvh; CHECK_NO_THROW(dvh = myDVHCalc2.generateDVH()); CHECK(dvh); CHECK_CLOSE(dvh->getDeltaD(), 0.1, errorConstant); //create dummy MaskAccessor boost::shared_ptr spTestMaskAccessor = boost::make_shared(spDoseAccessor->getGeometricInfo()); MaskAccessorPointer spMaskAccessor(spTestMaskAccessor); //create corresponding MaskedDoseIterator boost::shared_ptr spTestMaskedDoseIterator = boost::make_shared(spMaskAccessor, spDoseAccessor); MaskedDoseIteratorPointer spMaskedDoseIterator(spTestMaskedDoseIterator); CHECK_NO_THROW(core::DVHCalculator myDVHCalc3(spMaskedDoseIterator, structureID, doseID)); core::DVHCalculator myDVHCalc3(spMaskedDoseIterator, structureID, doseID); CHECK_NO_THROW(dvh = myDVHCalc3.generateDVH()); CHECK(dvh); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/DVHSetTest.cpp b/testing/core/DVHSetTest.cpp index 5c25455..04ee3a4 100644 --- a/testing/core/DVHSetTest.cpp +++ b/testing/core/DVHSetTest.cpp @@ -1,201 +1,193 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include - -#include -#include -#include - +#include "DummyDVHGenerator.h" #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbDVH.h" #include "rttbDVHSet.h" -#include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" -#include "DummyDVHGenerator.h" +#include namespace rttb { namespace testing { typedef core::DVHSet::DVHSetType DVHSetType; /*! @brief DVHTest - test the API of DVH 1) test constructors (values as expected?) 2) test size 3) test set/getIDs 4) test insert/retrieve individual DVHs 5) test getDVHSet 6) test getVolume */ int DVHSetTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; const IDType structureSetID = "myStructureSet"; const IDType structureIDPrefix = "myStructure"; const IDType doseID = "myDose"; DummyDVHGenerator dvhGenerator; DVHSetType tvSet; IDType structureID = structureIDPrefix + "_TV_"; for (int i = 0; i < 3; i++) { tvSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); } DVHSetType htSet; structureID = structureIDPrefix + "_HT_"; for (int i = 0; i < 5; i++) { htSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); } DVHSetType wvSet; structureID = structureIDPrefix + "_WV_"; for (int i = 0; i < 1; i++) { wvSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); } //1) test constructors (values as expected?) CHECK_NO_THROW(core::DVHSet(structureSetID, doseID)); CHECK_NO_THROW(core::DVHSet(tvSet, htSet, structureSetID, doseID)); CHECK_NO_THROW(core::DVHSet(tvSet, htSet, wvSet, structureSetID, doseID)); //2) test size core::DVHSet myDvhSet1(structureSetID, doseID); CHECK_EQUAL(myDvhSet1.size(), 0); core::DVHSet myDvhSet2(tvSet, htSet, structureSetID, doseID); CHECK_EQUAL(myDvhSet2.size(), tvSet.size() + htSet.size()); core::DVHSet myDvhSet3(tvSet, htSet, wvSet, structureSetID, doseID); CHECK_EQUAL(myDvhSet3.size(), tvSet.size() + htSet.size() + wvSet.size()); //3) test set/getIDs const IDType newStructureSetID = "myNewStructureSet"; const IDType newDoseID = "myNewDose"; CHECK_EQUAL(myDvhSet1.getStrSetID(), structureSetID); CHECK_EQUAL(myDvhSet1.getDoseID(), doseID); CHECK_NO_THROW(myDvhSet1.setStrSetID(newStructureSetID)); CHECK_NO_THROW(myDvhSet1.setDoseID(newDoseID)); CHECK_EQUAL(myDvhSet1.getStrSetID(), newStructureSetID); CHECK_EQUAL(myDvhSet1.getDoseID(), newDoseID); CHECK_EQUAL(myDvhSet3.getStrSetID(), structureSetID); CHECK_EQUAL(myDvhSet3.getDoseID(), doseID); CHECK_NO_THROW(myDvhSet3.setStrSetID(newStructureSetID)); CHECK_NO_THROW(myDvhSet3.setDoseID(newDoseID)); CHECK_EQUAL(myDvhSet3.getStrSetID(), newStructureSetID); CHECK_EQUAL(myDvhSet3.getDoseID(), newDoseID); //4) test insert/retrieve individual DVHs DVHRole roleTV = {DVHRole::TargetVolume}; DVHRole roleUser = { DVHRole::UserDefined }; structureID = structureIDPrefix + "_TV_"; core::DVH tv = dvhGenerator.generateDVH(structureID + boost::lexical_cast (tvSet.size()), doseID); CHECK_EQUAL(myDvhSet1.size(), 0); CHECK_NO_THROW(myDvhSet1.insert(tv, roleTV)); CHECK_EQUAL(myDvhSet1.size(), 1); std::size_t currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(tv, roleTV)); CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); CHECK_THROW_EXPLICIT(myDvhSet2.insert(tv, roleUser), core::InvalidParameterException); DVHRole roleHT = {DVHRole::HealthyTissue}; structureID = structureIDPrefix + "_HT_"; core::DVH ht = dvhGenerator.generateDVH(structureID + boost::lexical_cast (htSet.size()), doseID); CHECK_EQUAL(myDvhSet1.size(), 1); CHECK_NO_THROW(myDvhSet1.insert(ht, roleHT)); CHECK_EQUAL(myDvhSet1.size(), 2); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(ht, roleHT)); CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); DVHRole roleWV = {DVHRole::WholeVolume}; structureID = structureIDPrefix + "_wv_"; IDType testID = structureID + boost::lexical_cast(wvSet.size()); core::DVH wv = dvhGenerator.generateDVH(structureID + boost::lexical_cast (wvSet.size()), doseID); CHECK_EQUAL(myDvhSet1.size(), 2); CHECK_NO_THROW(myDvhSet1.insert(wv, roleWV)); CHECK_EQUAL(myDvhSet1.size(), 3); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(wv, roleWV)); CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); //5) test getDVHSet core::DVH* dvhPtr = myDvhSet1.getDVH(testID); CHECK_EQUAL(*dvhPtr, wv); dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_TV_0"); CHECK_EQUAL(*dvhPtr, tvSet.at(0)); dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_TV_2"); CHECK_EQUAL(*dvhPtr, tvSet.at(2)); dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_HT_2"); CHECK_EQUAL(*dvhPtr, htSet.at(2)); dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_WV_0"); CHECK_EQUAL(*dvhPtr, wvSet.at(0)); dvhPtr = myDvhSet3.getDVH("wrongID"); CHECK(!dvhPtr); DVHSetType tvTest = myDvhSet3.getTargetVolumeSet(); CHECK_EQUAL(tvTest, tvSet); DVHSetType htTest = myDvhSet3.getHealthyTissueSet(); CHECK_EQUAL(htTest, htSet); DVHSetType wvTest = myDvhSet3.getWholeVolumeSet(); CHECK_EQUAL(wvTest, wvSet); //6) test getVolume DoseTypeGy aDoseAbsolute = 10; CHECK_EQUAL(0, myDvhSet3.getHealthyTissueVolume(aDoseAbsolute)); CHECK_EQUAL(0, myDvhSet3.getTargetVolume(aDoseAbsolute)); CHECK_EQUAL(0, myDvhSet3.getWholeVolume(aDoseAbsolute)); //7) Test equality core::DVHSet myDvhSet4(myDvhSet1.getStrSetID(), myDvhSet1.getDoseID()); myDvhSet4.insert(tv, roleTV); myDvhSet4.insert(ht, roleHT); myDvhSet4.insert(wv, roleWV); CHECK_EQUAL(myDvhSet1 == myDvhSet2, false); CHECK_EQUAL(myDvhSet1 == myDvhSet4, true); myDvhSet4.setDoseID("bla"); CHECK_EQUAL(myDvhSet1 == myDvhSet4, false); myDvhSet4.setDoseID(myDvhSet1.getDoseID()); myDvhSet4.insert(tv, roleTV); CHECK_EQUAL(myDvhSet1 == myDvhSet4, false); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/DVHTest.cpp b/testing/core/DVHTest.cpp index fc34f66..a39258a 100644 --- a/testing/core/DVHTest.cpp +++ b/testing/core/DVHTest.cpp @@ -1,236 +1,229 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include - -#include -#include - #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbDVH.h" -#include "DummyDoseAccessor.h" -#include "DummyMaskAccessor.h" + namespace rttb { namespace testing { typedef core::DVH::DataDifferentialType DataDifferentialType; /*! @brief DVHTest - test the API of DVH 1) test constructors (values as expected?) 2) test assignement 3) test set/getLabel 4) test set/get 5) test equality */ int DVHTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; DataDifferentialType anEmptyDataDifferential; DataDifferentialType aDataDifferential; DataDifferentialType aDataDifferential2; DataDifferentialType aDataDifferentialRelative; DoseStatisticType maximum = 0; DoseStatisticType minimum = 0; double sum = 0; double squareSum = 0; DoseCalcType value = 0; DVHVoxelNumber numberOfVoxels = 0; // creat default values [0,100) for (int i = 0; i < 100; i++) { value = DoseCalcType((double(rand()) / RAND_MAX) * 1000); numberOfVoxels += value; aDataDifferential.push_back(value); aDataDifferential2.push_back(value * 10); if (value > 0) { maximum = (i + 0.5) * binSize; if (minimum == 0) { minimum = (i + 0.5) * binSize; } } sum += value * (i + 0.5) * binSize; squareSum += value * pow((i + 0.5) * binSize, 2); } double medianVoxel = 0; double modalVoxel = 0; unsigned int count = 0; unsigned int medianCount = 0; unsigned int modalCount = 0; for (const auto& aValue : aDataDifferential) { std::cout << aValue << std::endl; if (medianVoxel < numberOfVoxels - medianVoxel) { medianVoxel += aValue; medianCount = count; } if (modalVoxel < aValue) { modalVoxel = aValue; modalCount = count; } count++; } DoseStatisticType median = (medianCount + 0.5)*binSize; DoseStatisticType modal = (modalCount + 0.5)*binSize; DoseStatisticType mean = sum / numberOfVoxels; DoseStatisticType variance = (squareSum / numberOfVoxels - mean * mean); DoseStatisticType stdDeviation = pow(variance, 0.5); std::deque::iterator it; for (it = aDataDifferential.begin(); it != aDataDifferential.end(); ++it) { aDataDifferentialRelative.push_back((*it) / numberOfVoxels); } IDType structureID = "myStructure"; IDType doseID = "myDose"; IDType voxelizationID = "myVoxelization"; //1) test default constructor (values as expected?) CHECK_THROW(core::DVH(anEmptyDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(anEmptyDataDifferential, binSize, voxelVolume, structureID, doseID)); CHECK_NO_THROW(core::DVH(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID)); CHECK_NO_THROW(core::DVH(aDataDifferential, binSize, voxelVolume, structureID, doseID)); CHECK_THROW(core::DVH(aDataDifferential, 0, voxelVolume, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(aDataDifferential, 0, voxelVolume, structureID, doseID)); CHECK_THROW(core::DVH(aDataDifferential, binSize, 0, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(aDataDifferential, binSize, 0, structureID, doseID)); //2) test assignment core::DVH myTestDVH(aDataDifferential, binSize, voxelVolume, structureID, doseID); CHECK_NO_THROW(core::DVH myOtherDVH = myTestDVH); core::DVH myOtherDVH(myTestDVH); CHECK_NO_THROW(myOtherDVH = myTestDVH); //3) test set/getLabel core::DVH myDVH(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); StructureLabel label = ""; CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); label = "myLabel"; CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); label = "myLabel2"; CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); //4) test set/get //IDs CHECK_EQUAL(myDVH.getStructureID(), structureID); CHECK_EQUAL(myDVH.getDoseID(), doseID); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); /*! is related to #2029*/ myDVH.setDoseID("somethingElse"); CHECK_EQUAL(myDVH.getDoseID(), "somethingElse"); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); CHECK_EQUAL(myDVH.getStructureID(), structureID); /*! is related to #2029*/ myDVH.setStructureID("somethingOther"); CHECK_EQUAL(myDVH.getDoseID(), "somethingElse"); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); CHECK_EQUAL(myDVH.getStructureID(), "somethingOther"); //dataDifferential CHECK(myDVH.getDataDifferential() == aDataDifferential); CHECK(myDVH.getDataDifferential() == aDataDifferential); CHECK(myDVH.convertAbsoluteToRelative(false) == aDataDifferentialRelative); CHECK_EQUAL(myDVH.getNumberOfVoxels(), numberOfVoxels); CHECK_EQUAL(myDVH.getDeltaV(), voxelVolume); CHECK_EQUAL(myDVH.getDeltaD(), binSize); CHECK_EQUAL(myDVH.getMaximum(), maximum); CHECK_EQUAL(myDVH.getMinimum(), minimum); CHECK_EQUAL(myDVH.getMean(), mean); CHECK_EQUAL(myDVH.getVariance(), variance); CHECK_EQUAL(myDVH.getStdDeviation(), stdDeviation); CHECK_EQUAL(myDVH.getMedian(), median); CHECK_EQUAL(myDVH.getModal(), modal); //We can't test for absolute values as the implementation of rand() differs depending on compiler and different DVHs are created CHECK_NO_THROW(myDVH.getVx(0)); CHECK_NO_THROW(myDVH.getVx(7)); CHECK_NO_THROW(myDVH.getDx(0)); CHECK_NO_THROW(myDVH.getDx(100000)); int percentage = 20; VolumeType absVol = VolumeType(percentage * numberOfVoxels * voxelVolume / 100.0); CHECK_EQUAL(myDVH.getAbsoluteVolume(percentage), absVol); //5) test equality structureID = myDVH.getStructureID(); doseID = myDVH.getDoseID(); voxelizationID = myDVH.getVoxelizationID(); core::DVH myDVH2(aDataDifferential2, binSize, voxelVolume, structureID, doseID); core::DVH myDVH3(aDataDifferential, binSize, voxelVolume, structureID+"_diff", doseID); core::DVH myDVH4(aDataDifferential, binSize, voxelVolume, structureID, doseID+"_diff"); core::DVH myDVH5(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID+"_diff"); CHECK(!(myDVH == myDVH2)); CHECK(!(myDVH == myDVH3)); CHECK(!(myDVH == myDVH4)); CHECK(!(myDVH == myDVH5)); CHECK_EQUAL(myDVH, myDVH); core::DVH aDVH(myOtherDVH); CHECK_EQUAL(aDVH, myOtherDVH); std::map normalizedDVHDiff = myDVH.getNormalizedDVH({ DVHType::Differential }); for (auto elem : normalizedDVHDiff) { CHECK_EQUAL(aDataDifferential.at(std::round(elem.first / binSize)), (elem.second / voxelVolume)); } std::map normalizedDVHCum = myDVH.getNormalizedDVH(); for (auto elem : normalizedDVHCum) { CHECK_EQUAL(myDVH.getDataCumulative().at(std::round(elem.first / binSize)), (elem.second / voxelVolume)); } CHECK_NO_THROW(myDVH.getDataCumulative()); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/DummyDoseAccessor.cpp b/testing/core/DummyDoseAccessor.cpp index d88c09c..6650244 100644 --- a/testing/core/DummyDoseAccessor.cpp +++ b/testing/core/DummyDoseAccessor.cpp @@ -1,94 +1,92 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include #include "DummyDoseAccessor.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidDoseException.h" #include "rttbIndexOutOfBoundsException.h" namespace rttb { namespace testing { DummyDoseAccessor::~DummyDoseAccessor() {} DummyDoseAccessor::DummyDoseAccessor() { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _doseUID = "DummyDoseAccessor_" + ss.str(); assembleGeometricInfo(); for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) { doseData.push_back((double(rand()) / RAND_MAX) * 1000); } } DummyDoseAccessor::DummyDoseAccessor(const std::vector& aDoseVector, const core::GeometricInfo& geoInfo) { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _doseUID = "DummyDoseAccessor_" + ss.str(); doseData = aDoseVector; _geoInfo = geoInfo; } void DummyDoseAccessor::assembleGeometricInfo() { SpacingVectorType3D aVector(2.5); _geoInfo.setSpacing(aVector); WorldCoordinate3D anOtherVector(-25, -2, 35); _geoInfo.setImagePositionPatient(anOtherVector); _geoInfo.setNumRows(11); _geoInfo.setNumColumns(10); _geoInfo.setNumSlices(10); OrientationMatrix unit = OrientationMatrix(); _geoInfo.setOrientationMatrix(unit); } GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridID aID) const { if (!_geoInfo.validID(aID)) { throw core::IndexOutOfBoundsException("Not a valid Position!"); } return doseData.at(aID); } GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { VoxelGridID gridID = 0; _geoInfo.convert(aIndex, gridID); return getValueAt(gridID); } }//end namespace testing }//end namespace rttb \ No newline at end of file diff --git a/testing/core/DummyMaskAccessor.cpp b/testing/core/DummyMaskAccessor.cpp index f6401e7..421ce3d 100644 --- a/testing/core/DummyMaskAccessor.cpp +++ b/testing/core/DummyMaskAccessor.cpp @@ -1,156 +1,154 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include #include #include "DummyMaskAccessor.h" -#include "rttbNullPointerException.h" namespace rttb { namespace testing { DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo) { _spRelevantVoxelVector = MaskVoxelListPointer(); _geoInfo = aGeometricInfo; boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "DummyMask_" + ss.str(); } DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, MaskVoxelListPointer voxelListPtr) { _spRelevantVoxelVector = voxelListPtr; _geoInfo = aGeometricInfo; boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "DummyMask_" + ss.str(); } void DummyMaskAccessor::updateMask() { MaskVoxelList newRelevantVoxelVector; if (_spRelevantVoxelVector) { return; } for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) { if ((double(rand()) / RAND_MAX) > 0.5) { core::MaskVoxel newMaskVoxel(i); newMaskVoxel.setRelevantVolumeFraction((double(rand()) / RAND_MAX)); newRelevantVoxelVector.push_back(newMaskVoxel); } } _spRelevantVoxelVector = boost::make_shared(newRelevantVoxelVector); return; } DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector() { updateMask(); return _spRelevantVoxelVector; } DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector( float lowerThreshold) { auto filteredVoxelVectorPointer = boost::make_shared(); updateMask(); DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } ++it; } return filteredVoxelVectorPointer; } bool DummyMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { voxel.setRelevantVolumeFraction(0); if (!_geoInfo.validID(aID)) { return false; } if (_spRelevantVoxelVector) { DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getVoxelGridID() == aID) { voxel = (*it); return true; } ++it; } } else { return false; } return false; } bool DummyMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getMaskAt(aVoxelGridID, voxel); } else { return false; } } } } \ No newline at end of file diff --git a/testing/core/DummyMutableDoseAccessor.cpp b/testing/core/DummyMutableDoseAccessor.cpp index ed82584..5bc5b78 100644 --- a/testing/core/DummyMutableDoseAccessor.cpp +++ b/testing/core/DummyMutableDoseAccessor.cpp @@ -1,114 +1,111 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -#include -#include -#include - #include "DummyMutableDoseAccessor.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidDoseException.h" #include "rttbIndexOutOfBoundsException.h" +#include +#include + namespace rttb { namespace testing { DummyMutableDoseAccessor::~DummyMutableDoseAccessor() {} DummyMutableDoseAccessor::DummyMutableDoseAccessor() { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _doseUID = "DummyMutableDoseAccessor_" + ss.str(); SpacingVectorType3D aVector(2.5); _geoInfo.setSpacing(aVector); WorldCoordinate3D anOtherVector(-25, -2, 35); _geoInfo.setImagePositionPatient(anOtherVector); _geoInfo.setNumRows(11); _geoInfo.setNumColumns(10); _geoInfo.setNumSlices(5); OrientationMatrix unit = OrientationMatrix(); _geoInfo.setOrientationMatrix(unit); for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) { doseData.push_back((double(rand()) / RAND_MAX) * 1000); } } DummyMutableDoseAccessor::DummyMutableDoseAccessor(const std::vector& aDoseVector, const core::GeometricInfo& geoInfo) { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _doseUID = "DummyMutableDoseAccessor_" + ss.str(); doseData = aDoseVector; _geoInfo = geoInfo; } const core::GeometricInfo& DummyMutableDoseAccessor:: getGeometricInfo() const { return _geoInfo; } GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridID aID) const { if (!_geoInfo.validID(aID)) { throw core::IndexOutOfBoundsException("Not a valid Position!"); } return doseData.at(aID); } GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { VoxelGridID gridID = 0; _geoInfo.convert(aIndex, gridID); return getValueAt(gridID); } void DummyMutableDoseAccessor::setDoseAt(const VoxelGridID aID, DoseTypeGy value) { if (!_geoInfo.validID(aID)) { throw core::IndexOutOfBoundsException("Not a valid Position!"); } doseData.at(aID) = value; } void DummyMutableDoseAccessor::setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value) { VoxelGridID gridID = 0; _geoInfo.convert(aIndex, gridID); setDoseAt(gridID, value); } }//end namespace testing }//end namespace rttb \ No newline at end of file diff --git a/testing/core/DummyStructure.cpp b/testing/core/DummyStructure.cpp index 3345ff0..f4b4bd5 100644 --- a/testing/core/DummyStructure.cpp +++ b/testing/core/DummyStructure.cpp @@ -1,742 +1,737 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include - #include "DummyStructure.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" -#include "rttbInvalidDoseException.h" namespace rttb { namespace testing { DummyStructure::~DummyStructure() {} DummyStructure::DummyStructure(const core::GeometricInfo& aGeoInfo) { _geoInfo = aGeoInfo; } core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 1); VoxelGridIndex2D another_i2(5, 1); VoxelGridIndex2D another_i3(5, 5); VoxelGridIndex2D another_i4(2, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); return test_structure_rectangular_centered; } core::Structure DummyStructure::CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 1); VoxelGridIndex2D another_i2(5, 1); VoxelGridIndex2D another_i3(5, 5); VoxelGridIndex2D another_i4(2, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector, zPlane); PolygonType another_polygon2 = another_cts.createPolygonCenterOnPlaneCenter(another_voxelVector, zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); another_polySeq.push_back(another_polygon2); core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); return test_structure_rectangular_centered; } core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 1); VoxelGridIndex2D another_i2(5, 1); VoxelGridIndex2D another_i3(5, 5); VoxelGridIndex2D another_i4(2, 5); PolygonSequenceType another_polySeq; for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ another_voxelVector.clear(); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector, i); another_polySeq.push_back(another_polygon1); } core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); return test_structure_rectangular_centered; } core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane, GridIndexType fromZPlane2, GridIndexType toZPlane2) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 1); VoxelGridIndex2D another_i2(5, 1); VoxelGridIndex2D another_i3(5, 5); VoxelGridIndex2D another_i4(2, 5); PolygonSequenceType another_polySeq; for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ another_voxelVector.clear(); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector, i); another_polySeq.push_back(another_polygon1); } for (unsigned int i = fromZPlane2; i <= toZPlane2; ++i){ another_voxelVector.clear(); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector, i); another_polySeq.push_back(another_polygon1); } core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); return test_structure_rectangular_centered; } core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacement( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(5, 1); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(5, 7); VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonBetweenUpperLeftAndCenter( another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight() { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(5, 1); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(5, 7); VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonSequenceType another_polySeq; core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClock( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i2(5, 7); VoxelGridIndex2D another_i3(8, 4); VoxelGridIndex2D another_i4(5, 1); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonBetweenLowerRightAndCenter( another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClockIntermediatePoints( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i2(5, 7); VoxelGridIndex2D another_i3(8, 4); VoxelGridIndex2D another_i4(5, 1); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonIntermediatePoints(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureSeveralSeperateSectionsInsideOneVoxel( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 2); another_voxelVector.push_back(another_i1); PolygonType another_polygon1 = another_cts.createStructureSeveralSectionsInsideOneVoxelA( another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureSelfTouchingA(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 2); another_voxelVector.push_back(another_i1); PolygonType another_polygon1 = another_cts.createStructureSelfTouchingA(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygonsInDifferentSlices( GridIndexType zPlane1, GridIndexType zPlane2) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); CreateTestStructure one_more_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(8, 6); VoxelGridIndex2D another_i4(2, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane1); std::vector one_more_voxelVector; VoxelGridIndex2D one_more_i1(3, 5); VoxelGridIndex2D one_more_i2(9, 5); VoxelGridIndex2D one_more_i3(9, 7); VoxelGridIndex2D one_more_i4(3, 7); one_more_voxelVector.push_back(one_more_i1); one_more_voxelVector.push_back(one_more_i2); one_more_voxelVector.push_back(one_more_i3); one_more_voxelVector.push_back(one_more_i4); PolygonType another_polygon2 = one_more_cts.createPolygonCenter(one_more_voxelVector , zPlane2); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); another_polySeq.push_back(another_polygon2); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygons(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); CreateTestStructure one_more_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(8, 6); VoxelGridIndex2D another_i4(2, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); std::vector one_more_voxelVector; VoxelGridIndex2D one_more_i1(3, 5); VoxelGridIndex2D one_more_i2(9, 5); VoxelGridIndex2D one_more_i3(9, 7); VoxelGridIndex2D one_more_i4(3, 7); one_more_voxelVector.push_back(one_more_i1); one_more_voxelVector.push_back(one_more_i2); one_more_voxelVector.push_back(one_more_i3); one_more_voxelVector.push_back(one_more_i4); PolygonType another_polygon2 = one_more_cts.createPolygonCenter(one_more_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); another_polySeq.push_back(another_polygon2); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureIntersecting(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(2, 6); VoxelGridIndex2D another_i4(8, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouches(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(3, 4); VoxelGridIndex2D another_i2(2, 8); VoxelGridIndex2D another_i3(4, 8); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); PolygonType another_polygon1 = another_cts.createPolygonUpperCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedPointDoubeled( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 4); VoxelGridIndex2D another_i4(2, 4); VoxelGridIndex2D another_i2(4, 4); VoxelGridIndex2D another_i3(3, 8); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); PolygonType another_polygon1 = another_cts.createPolygonUpperCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedOnePointFivePi( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(3, 5); VoxelGridIndex2D another_i2(3, 5); VoxelGridIndex2D another_i3(7, 6); VoxelGridIndex2D another_i4(7, 6); VoxelGridIndex2D another_i5(7, 4); VoxelGridIndex2D another_i6(7, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedQuaterPi( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(7, 5); VoxelGridIndex2D another_i2(7, 5); VoxelGridIndex2D another_i3(3, 6); VoxelGridIndex2D another_i4(3, 6); VoxelGridIndex2D another_i5(3, 4); VoxelGridIndex2D another_i6(3, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedQuaterPi( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(3, 4); VoxelGridIndex2D another_i2(3, 4); VoxelGridIndex2D another_i3(3, 6); VoxelGridIndex2D another_i4(3, 6); VoxelGridIndex2D another_i5(7, 5); VoxelGridIndex2D another_i6(7, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureCircle(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(4, 4); another_voxelVector.push_back(another_i1); PolygonType another_polygon1 = another_cts.createPolygonCircle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperRight( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(3, 4); VoxelGridIndex2D another_i3(4, 5); VoxelGridIndex2D another_i5(5, 3); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i5); PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerRight( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(2, 2); VoxelGridIndex2D another_i2(2, 2); VoxelGridIndex2D another_i3(3, 1); VoxelGridIndex2D another_i4(3, 1); VoxelGridIndex2D another_i5(4, 3); VoxelGridIndex2D another_i6(4, 3); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerLeft( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(3, 3); VoxelGridIndex2D another_i2(3, 3); VoxelGridIndex2D another_i3(4, 4); VoxelGridIndex2D another_i4(4, 4); VoxelGridIndex2D another_i5(2, 5); VoxelGridIndex2D another_i6(2, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperLeft( GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(5, 5); VoxelGridIndex2D another_i2(5, 5); VoxelGridIndex2D another_i3(4, 6); VoxelGridIndex2D another_i4(4, 6); VoxelGridIndex2D another_i5(3, 4); VoxelGridIndex2D another_i6(3, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } void DummyStructure::ShowTestStructure(core::Structure aStructure) { WorldCoordinate3D aPoint(0); PolygonSequenceType strVector = aStructure.getStructureVector(); for (size_t struct_index = 0 ; struct_index < strVector.size() ; struct_index++) { for (size_t point_index = 0 ; point_index < strVector.at(struct_index).size() ; point_index++) { aPoint = strVector.at(struct_index).at(point_index); std::cout << " aPoint.x " << aPoint.x() << std::endl; std::cout << " aPoint.y " << aPoint.y() << std::endl; std::cout << " aPoint.z " << aPoint.z() << std::endl; } } } core::Structure DummyStructure::CreateRectangularStructureUpperLeftRotated(GridIndexType zPlane) { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; VoxelGridIndex2D another_i1(5, 1); VoxelGridIndex2D another_i2(8, 4); VoxelGridIndex2D another_i3(5, 7); VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; another_polySeq.push_back(another_polygon1); core::Structure test_structure = core::Structure(another_polySeq); return test_structure; } }//testing }//rttb diff --git a/testing/core/GenericDoseIteratorTest.cpp b/testing/core/GenericDoseIteratorTest.cpp index 7894dbc..290bc37 100644 --- a/testing/core/GenericDoseIteratorTest.cpp +++ b/testing/core/GenericDoseIteratorTest.cpp @@ -1,106 +1,104 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" -#include "DummyDoseAccessor.h" #include "DummyInhomogeneousDoseAccessor.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief GenericDoseIteratorTest - test the API of GenericDoseIterator 1) test constructor (values as expected?) 2) test reset/next/get current values/isPositionValid 3) test DoseIteratorInterface functions */ int GenericDoseIteratorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //create dummy DoseAccessor boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseAccessorInhomo = boost::make_shared(); DoseAccessorPointer spDoseAccessorInhomo(spTestDoseAccessorInhomo); //1) test constructor (values as expected?) CHECK_NO_THROW(core::GenericDoseIterator genDoseIterator(spDoseAccessor)); core::GenericDoseIterator genDoseIterator(spDoseAccessor); const VoxelGridID defaultDoseVoxelGridID = 0; const DoseVoxelVolumeType defaultVoxelVolume = 0; CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK_EQUAL(defaultVoxelVolume, genDoseIterator.getCurrentVoxelVolume()); core::GenericDoseIterator genDoseIteratorInhomo(spDoseAccessorInhomo); //2) test reset/next genDoseIterator.reset(); const DoseVoxelVolumeType homogeneousVoxelVolume = genDoseIterator.getCurrentVoxelVolume(); CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK(!(defaultVoxelVolume == genDoseIterator.getCurrentVoxelVolume())); core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); SpacingVectorType3D spacing = geoInfo.getSpacing(); CHECK_EQUAL(spacing(0)*spacing(1)*spacing(2) / 1000, genDoseIterator.getCurrentVoxelVolume()); CHECK_THROW_EXPLICIT(genDoseIteratorInhomo.reset(), core::InvalidParameterException); //check if the correct voxels are accessed const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); genDoseIterator.reset(); VoxelGridID position = 0; while (genDoseIterator.isPositionValid()) { CHECK_EQUAL(genDoseIterator.getCurrentDoseValue(), doseVals->at(position)); CHECK_EQUAL(homogeneousVoxelVolume, genDoseIterator.getCurrentVoxelVolume()); CHECK_EQUAL(1, genDoseIterator.getCurrentRelevantVolumeFraction()); CHECK_EQUAL(position, genDoseIterator.getCurrentVoxelGridID()); genDoseIterator.next(); position++; } CHECK_EQUAL(spTestDoseAccessor->getGridSize(), spTestDoseAccessor->getGeometricInfo().getNumberOfVoxels()); //check isPositionValid() in invalid positions CHECK(!(genDoseIterator.isPositionValid())); //after end of dose CHECK_EQUAL(genDoseIterator.getCurrentDoseValue(), 0); genDoseIterator.reset(); CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK(genDoseIterator.isPositionValid());//before start of dose //3) test DoseIteratorInterface functions CHECK_EQUAL(genDoseIterator.getVoxelizationID(), ""); CHECK_EQUAL(genDoseIterator.getDoseUID(), spTestDoseAccessor->getUID()); CHECK_THROW_EXPLICIT(genDoseIteratorInhomo.getCurrentVoxelVolume(), core::InvalidParameterException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/GenericMaskedDoseIteratorTest.cpp b/testing/core/GenericMaskedDoseIteratorTest.cpp index 6ba9097..2535523 100644 --- a/testing/core/GenericMaskedDoseIteratorTest.cpp +++ b/testing/core/GenericMaskedDoseIteratorTest.cpp @@ -1,137 +1,133 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" -#include "rttbException.h" -#include "DummyDoseAccessor.h" #include "DummyInhomogeneousDoseAccessor.h" #include "DummyMaskAccessor.h" namespace rttb { namespace testing { typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::GenericMaskedDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief GenericMaskedDoseIteratorTest. 1) test constructor (values as expected?) 2) test reset/next/get current values/isPositionValid */ int GenericMaskedDoseIteratorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseAccessorInhomo = boost::make_shared(); DoseAccessorPointer spDoseAccessorInhomo(spTestDoseAccessorInhomo); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); core::GeometricInfo geoInfo; boost::shared_ptr spTestMaskAccessor = boost::make_shared (geoInfo); MaskAccessorPointer spMaskAccessor(spTestMaskAccessor); //1) test constructor (values as expected?) //not nullptr MaskAccessorPointer spNullMaskAccessor; DoseAccessorPointer spNullDoseAccessor; CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spNullMaskAccessor, spDoseAccessor), core::NullPointerException); CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spNullDoseAccessor), core::NullPointerException); //not same core::GeometricInfo CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor), core::Exception); //set correct GeometricInfo geoInfo = spDoseAccessor->getGeometricInfo(); boost::shared_ptr spTestMaskAccessor1 = boost::make_shared (geoInfo); MaskAccessorPointer spMaskAccessorTemp(spTestMaskAccessor1); spMaskAccessor.swap(spMaskAccessorTemp); CHECK_NO_THROW(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor)); CHECK_EQUAL(spMaskAccessor->isGridHomogeneous(), true); core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor); core::GenericMaskedDoseIterator genMaskedDoseIteratorInhomo(spMaskAccessor, spDoseAccessorInhomo); //2) test reset/next const DummyMaskAccessor::MaskVoxelListPointer maskedVoxelListPtr = spTestMaskAccessor1->getRelevantVoxelVector(); genMaskedDoseIterator.reset(); const DoseVoxelVolumeType homogeneousVoxelVolume = genMaskedDoseIterator.getCurrentVoxelVolume(); CHECK_EQUAL((maskedVoxelListPtr->begin())->getVoxelGridID(), genMaskedDoseIterator.getCurrentVoxelGridID()); geoInfo = spDoseAccessor->getGeometricInfo(); SpacingVectorType3D spacing = geoInfo.getSpacing(); CHECK_EQUAL(spacing(0)*spacing(1)*spacing(2) / 1000, genMaskedDoseIterator.getCurrentVoxelVolume()); CHECK_THROW_EXPLICIT(genMaskedDoseIteratorInhomo.getCurrentVoxelVolume(), core::InvalidParameterException); genMaskedDoseIterator.reset(); for (unsigned int i = 0; i < maskedVoxelListPtr->size(); i++) { CHECK_NO_THROW(genMaskedDoseIterator.next()); } CHECK_EQUAL(genMaskedDoseIterator.getCurrentRelevantVolumeFraction(), 0); //check if the correct voxels are accessed genMaskedDoseIterator.reset(); VoxelGridID defaultDoseVoxelGridID = genMaskedDoseIterator.getCurrentVoxelGridID(); DoseTypeGy controlValue = 0; VoxelGridID position = 0; while (genMaskedDoseIterator.isPositionValid()) { controlValue = doseVals->at((maskedVoxelListPtr->at(position)).getVoxelGridID()); CHECK_EQUAL(controlValue, genMaskedDoseIterator.getCurrentDoseValue()); controlValue = controlValue * (maskedVoxelListPtr->at(position)).getRelevantVolumeFraction(); CHECK_EQUAL(controlValue, genMaskedDoseIterator.getCurrentMaskedDoseValue()); CHECK_EQUAL(homogeneousVoxelVolume, genMaskedDoseIterator.getCurrentVoxelVolume()); CHECK_EQUAL((maskedVoxelListPtr->at(position)).getRelevantVolumeFraction(), genMaskedDoseIterator.getCurrentRelevantVolumeFraction()); CHECK_EQUAL((maskedVoxelListPtr->at(position)).getVoxelGridID(), genMaskedDoseIterator.getCurrentVoxelGridID()); CHECK(genMaskedDoseIterator.isPositionValid()); genMaskedDoseIterator.next(); position++; } //check isPositionValid() in invalid positions CHECK(!(genMaskedDoseIterator.isPositionValid())); //after end of dose genMaskedDoseIterator.reset(); CHECK_EQUAL(defaultDoseVoxelGridID, genMaskedDoseIterator.getCurrentVoxelGridID()); CHECK(genMaskedDoseIterator.isPositionValid());//at start of dose RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/core/GeometricInfoTest.cpp b/testing/core/GeometricInfoTest.cpp index 2e2ec50..00945a1 100644 --- a/testing/core/GeometricInfoTest.cpp +++ b/testing/core/GeometricInfoTest.cpp @@ -1,555 +1,554 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbGeometricInfo.h" namespace rttb { namespace testing { /*!@brief GeometricInfoTest - test the API of GeometricInfo @note ITK pixel indexing: Index[0] = col, Index[1] = row, Index[2] = slice. 1) test default constructor (values as expected?) 2) test set/getImagePositionPatient 4) test set/getSpacing 5) test set/getNumColumns/Rows/Slices 6) test get/setOrientationMatrix 8) test operators "==" 9) test equalsAlmost 10) test world to index coordinate conversion 11) test isInside and index to world coordinate conversion 12) test with simple Geometry: isInside, geometryCoordinateToWorldCoordinate(), worldCoordinateToGeometryCoordinate(), indexToWorldCoordinate() 13) test getNumberOfVoxels 14) Test convert, validID and validIndex */ int GeometricInfoTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) test default constructor (values as expected?) CHECK_NO_THROW(core::GeometricInfo()); core::GeometricInfo geoInfo; SpacingVectorType3D testNullSV(0); WorldCoordinate3D testNullWC(0); OrientationMatrix testNullOM(0); CHECK_EQUAL(testNullSV, geoInfo.getSpacing()); CHECK_EQUAL(testNullWC, geoInfo.getImagePositionPatient()); CHECK_EQUAL(testNullOM, geoInfo.getOrientationMatrix()); //2) test set/getImagePositionPatient WorldCoordinate3D testIPP(1.2, 3.4, 5.6); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); geoInfo.setImagePositionPatient(testIPP); CHECK_EQUAL(testIPP, geoInfo.getImagePositionPatient()); //4) test set/getSpacing //negative spacing does not make sense! /*!@is related to #2028 Should SpacingTypeVector/GridVolumeType/OrientationMatrix be forced to be non-negative?*/ SpacingVectorType3D expectedSpacing(4.15, 2.35, 100); expectedSpacing(0) = 4.15; expectedSpacing(1) = 2.35; expectedSpacing(2) = 100; CHECK_NO_THROW(geoInfo.setSpacing(expectedSpacing)); geoInfo.setSpacing(expectedSpacing); CHECK_EQUAL(expectedSpacing, geoInfo.getSpacing()); //5) test set/getNumColumns/Rows/Slices const VoxelGridIndex3D expectedVoxelDims(10, 5, 3); //CHECK_THROW(geoInfo.setNumColumns(1.2)); -> implicit conversion will prevent exception CHECK_NO_THROW(geoInfo.setNumColumns(expectedVoxelDims(0))); geoInfo.setNumColumns(expectedVoxelDims(0)); CHECK_NO_THROW(geoInfo.setNumRows(expectedVoxelDims(1))); geoInfo.setNumRows(expectedVoxelDims(1)); //CHECK_THROW(geoInfo.setNumSlices(4.2)); -> implicit conversion will prevent exception CHECK_NO_THROW(geoInfo.setNumSlices(expectedVoxelDims(2))); geoInfo.setNumSlices(expectedVoxelDims(2)); ImageSize rttbSize = geoInfo.getImageSize(); CHECK_EQUAL(rttbSize(0), geoInfo.getNumColumns()); CHECK_EQUAL(rttbSize(1), geoInfo.getNumRows()); CHECK_EQUAL(rttbSize(2), geoInfo.getNumSlices()); rttbSize = ImageSize(11, 99, 6); core::GeometricInfo geoInfo3; geoInfo3.setImageSize(rttbSize); CHECK_EQUAL(rttbSize(0), geoInfo3.getNumColumns()); CHECK_EQUAL(rttbSize(1), geoInfo3.getNumRows()); CHECK_EQUAL(rttbSize(2), geoInfo3.getNumSlices()); //6) test get/setOrientationMatrix CHECK_EQUAL(testNullOM, geoInfo.getOrientationMatrix()); OrientationMatrix testOM(0); const WorldCoordinate3D testIORow(5.5, 4.7, 3.2); const WorldCoordinate3D testIOColumn(2.5, 1.8, 9.1); WorldCoordinate3D ortho = testIORow.cross(testIOColumn); testOM(0, 0) = testIORow(0); testOM(1, 0) = testIORow(1); testOM(2, 0) = testIORow(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); testOM(0, 1) = testIOColumn(0); testOM(1, 1) = testIOColumn(1); testOM(2, 1) = testIOColumn(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); testOM(0, 2) = ortho(0); testOM(1, 2) = ortho(1); testOM(2, 2) = ortho(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); //8) test operators "==" core::GeometricInfo geoInfo2; CHECK_EQUAL(geoInfo, geoInfo); CHECK(!(geoInfo == geoInfo2)); CHECK_EQUAL(geoInfo.getOrientationMatrix(), testOM); CHECK(!(geoInfo.getOrientationMatrix() == testNullOM)); //9) test equalsALmost OrientationMatrix testOM2 = testOM; SpacingVectorType3D testSPV2 = expectedSpacing; WorldCoordinate3D testIPP2 = testIPP; core::GeometricInfo testGI2, testGIEmpty; testGI2.setImagePositionPatient(testIPP2); testGI2.setOrientationMatrix(testOM2); testGI2.setSpacing(testSPV2); double smallValue = 0.000000001; testOM(0, 0) += smallValue; testSPV2(2) += smallValue; testIPP2(1) += smallValue; core::GeometricInfo testGI2similar; testGI2similar.setImagePositionPatient(testIPP2); testGI2similar.setOrientationMatrix(testOM2); testGI2similar.setSpacing(testSPV2); CHECK_EQUAL(testGI2.equalsAlmost(testGI2similar), true); CHECK_EQUAL(testGI2similar.equalsAlmost(testGI2), true); CHECK_EQUAL(testGI2.equalsAlmost(testGI2similar, smallValue * 0.001), false); CHECK_EQUAL(testGIEmpty.equalsAlmost(testGI2), false); CHECK_EQUAL(testGI2.equalsAlmost(testGIEmpty), false); //10) test world to index coordinate conversion //use unit matrix as orientation matrix CHECK_NO_THROW(geoInfo.setOrientationMatrix(OrientationMatrix())); //origin (inside) WorldCoordinate3D insideTestWC1 = geoInfo.getImagePositionPatient(); //inside const VoxelGridIndex3D expectedIndex(8, 3, 2); WorldCoordinate3D insideTestWC2(expectedIndex(0)*expectedSpacing(0) + testIPP(0), expectedIndex(1)*expectedSpacing(1) + testIPP(1), expectedIndex(2)*expectedSpacing(2) + testIPP(2)); //outside WorldCoordinate3D insideTestWC3(-33.12, 0, 14); // outside (dimension of grid) WorldCoordinate3D insideTestWC4(expectedVoxelDims(0)*expectedSpacing(0) + testIPP(0), expectedVoxelDims(1)*expectedSpacing(1) + testIPP(1), expectedVoxelDims(2)*expectedSpacing(2) + testIPP(2)); CHECK(geoInfo.isInside(insideTestWC1)); CHECK(geoInfo.isInside(insideTestWC2)); CHECK(!(geoInfo.isInside(insideTestWC3))); CHECK(!(geoInfo.isInside(insideTestWC4))); VoxelGridIndex3D testConvert(0); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC1, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(VoxelGridIndex3D(0), testConvert); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC2, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndex, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC3, testConvert))); //CHECK_EQUAL(VoxelGridIndex3D(0),testConvert); //if value is in a negative grid position it will be converted //to a very large unrelated number. CHECK(!(geoInfo.isInside(testConvert))); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC4, testConvert))); CHECK_EQUAL(expectedVoxelDims, testConvert); CHECK(!(geoInfo.isInside(testConvert))); //use a more complicated orientation matrix OrientationMatrix newOrientation(0); newOrientation(0, 0) = 0.5; newOrientation(1, 2) = -3; newOrientation(2, 1) = 1; CHECK_NO_THROW(geoInfo.setOrientationMatrix(newOrientation)); testIPP = WorldCoordinate3D(20, 100, -1000); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); CHECK_NO_THROW(geoInfo.setSpacing(SpacingVectorType3D(1))); //values for testing were generated with a dedicated MeVisLab routine insideTestWC1 = geoInfo.getImagePositionPatient(); //origin (inside) const VoxelGridIndex3D expectedIndexWC1(0, 0, 0); insideTestWC2 = WorldCoordinate3D(22.5, 97, -998); //inside const VoxelGridIndex3D expectedIndexWC2(5, 2, 1); insideTestWC3 = WorldCoordinate3D(26, 88, -996); //outside const VoxelGridIndex3D expectedIndexWC3(12, 4, 4); insideTestWC4 = WorldCoordinate3D(25, 91, -995); // outside: Grid dimension = [10,5,3] const VoxelGridIndex3D expectedIndexWC4(10, 5, 3); CHECK(geoInfo.isInside(insideTestWC1)); CHECK_EQUAL(geoInfo.isInside(insideTestWC1), geoInfo.isInside(expectedIndexWC1)); CHECK(geoInfo.isInside(insideTestWC2)); CHECK_EQUAL(geoInfo.isInside(insideTestWC2), geoInfo.isInside(expectedIndexWC2)); CHECK(!(geoInfo.isInside(insideTestWC3))); CHECK_EQUAL(geoInfo.isInside(insideTestWC3), geoInfo.isInside(expectedIndexWC3)); CHECK(!(geoInfo.isInside(insideTestWC4))); CHECK_EQUAL(geoInfo.isInside(insideTestWC4), geoInfo.isInside(expectedIndexWC4)); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC1, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndexWC1, testConvert); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC2, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndexWC2, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC3, testConvert))); CHECK(!(geoInfo.isInside(testConvert))); CHECK_EQUAL(expectedIndexWC3, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC4, testConvert))); CHECK(!(geoInfo.isInside(testConvert))); CHECK_EQUAL(expectedIndexWC4, testConvert); //11) test isInside and index to world coordinate conversion //use unit matrix as orientation matrix CHECK_NO_THROW(geoInfo.setOrientationMatrix(OrientationMatrix())); VoxelGridIndex3D insideTest1(0, 0, 0); //origin (inside) VoxelGridIndex3D insideTest2(2, 3, 1); //inside VoxelGridIndex3D insideTest3(0, 6, 14); //outside VoxelGridIndex3D insideTest4 = expectedVoxelDims; // outside CHECK(geoInfo.isInside(insideTest1)); CHECK(geoInfo.isInside(insideTest2)); CHECK(!(geoInfo.isInside(insideTest3))); CHECK(!(geoInfo.isInside(insideTest4))); WorldCoordinate3D testInside(0); CHECK(geoInfo.indexToWorldCoordinate(insideTest1, testInside)); CHECK(geoInfo.isInside(testInside)); //CHECK_EQUAL(geoInfo.getImagePositionPatient(),testInside); //half voxel shift prevents equality! CHECK(geoInfo.indexToWorldCoordinate(insideTest2, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest3, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest4, testInside))); CHECK(!(geoInfo.isInside(testInside))); WorldCoordinate3D testWorldCoordinate; DoubleVoxelGridIndex3D testDoubleIndex; DoubleVoxelGridIndex3D doubleIndex1 = DoubleVoxelGridIndex3D(0.1, 0, -0.3); const WorldCoordinate3D expectedDoubleIndex1(20.1, 100, -1000.3); DoubleVoxelGridIndex3D doubleIndex2 = DoubleVoxelGridIndex3D(11, 6, 15); //outside const WorldCoordinate3D expectedDoubleIndex2(31, 106, -985); DoubleVoxelGridIndex3D doubleIndex3 = DoubleVoxelGridIndex3D(10.1, 5.0, 3.0); // outside: Grid dimension = [10,5,3] const WorldCoordinate3D expectedDoubleIndex3(30.1, 105, -997); DoubleVoxelGridIndex3D doubleIndex4 = DoubleVoxelGridIndex3D(0.0, 0.0, 0.0); const WorldCoordinate3D expectedDoubleIndex4 = geoInfo.getImagePositionPatient(); //test double index to world coordinate geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex1); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex2); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex3); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex4, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex4); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex4, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex4); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex3, testDoubleIndex); CHECK_CLOSE(testDoubleIndex(0), doubleIndex3(0), errorConstant); CHECK_CLOSE(testDoubleIndex(1), doubleIndex3(1), errorConstant); CHECK_CLOSE(testDoubleIndex(2), doubleIndex3(2), errorConstant); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex2); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex1, testDoubleIndex); CHECK_CLOSE(testDoubleIndex(0), doubleIndex1(0), errorConstant); CHECK_CLOSE(testDoubleIndex(1), doubleIndex1(1), errorConstant); CHECK_CLOSE(testDoubleIndex(2), doubleIndex1(2), errorConstant); VoxelGridIndex3D testIntIndex; geoInfo.worldCoordinateToIndex(expectedDoubleIndex4, testIntIndex); CHECK_EQUAL(testIntIndex, insideTest1); geoInfo.worldCoordinateToIndex(expectedDoubleIndex1, testIntIndex); CHECK_EQUAL(testIntIndex, insideTest1); geoInfo.worldCoordinateToIndex(expectedDoubleIndex3, testIntIndex); CHECK_EQUAL(testIntIndex, expectedVoxelDims); //use a more complicated orientation matrix newOrientation = OrientationMatrix(0); newOrientation(0, 0) = 0.5; newOrientation(1, 2) = -3; newOrientation(2, 1) = 1; CHECK_NO_THROW(geoInfo.setOrientationMatrix(newOrientation)); testIPP = WorldCoordinate3D(20, 100, -1000); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); CHECK_NO_THROW(geoInfo.setSpacing(SpacingVectorType3D(1))); //values for testing were generated with a dedicated MeVisLab routine //no half voxel shift anymore because we changed indexToWorldCoordinate/worldCoordinateToIndex insideTest1 = VoxelGridIndex3D(0, 0, 0); //origin (inside) const WorldCoordinate3D expectedIndex1(20, 100, -1000); insideTest2 = VoxelGridIndex3D(6, 0, 2); //inside const WorldCoordinate3D expectedIndex2(23, 94, -1000); insideTest3 = VoxelGridIndex3D(11, 6, 15); //outside const WorldCoordinate3D expectedIndex3(25.5, 55, -994); insideTest4 = VoxelGridIndex3D(10, 5, 3); // outside: Grid dimension = [10,5,3] const WorldCoordinate3D expectedIndex4(25, 91, -995); CHECK(geoInfo.isInside(insideTest1)); CHECK_EQUAL(geoInfo.isInside(insideTest1), geoInfo.isInside(expectedIndex1)); CHECK(geoInfo.isInside(insideTest2)); CHECK_EQUAL(geoInfo.isInside(insideTest2), geoInfo.isInside(expectedIndex2)); CHECK(!(geoInfo.isInside(insideTest3))); CHECK_EQUAL(geoInfo.isInside(insideTest3), geoInfo.isInside(expectedIndex3)); CHECK(!(geoInfo.isInside(insideTest4))); CHECK_EQUAL(geoInfo.isInside(insideTest4), geoInfo.isInside(expectedIndex4)); CHECK(geoInfo.indexToWorldCoordinate(insideTest1, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK_EQUAL(expectedIndex1, testInside); CHECK(geoInfo.indexToWorldCoordinate(insideTest2, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK_EQUAL(expectedIndex2, testInside); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest3, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK_EQUAL(expectedIndex3, testInside); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest4, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK_EQUAL(expectedIndex4, testInside); //12) test with simple Geometry: isInside, geometryCoordinateToWorldCoordinate(), worldCoordinateToGeometryCoordinate(), indexToWorldCoordinate() core::GeometricInfo geoInfoSimple; ImageSize rttbSimpleSize = ImageSize(10, 10, 10); geoInfoSimple.setImageSize(rttbSimpleSize); SpacingVectorType3D spacingSimple(1, 1, 1); geoInfoSimple.setSpacing(spacingSimple); OrientationMatrix OMOnes; geoInfoSimple.setOrientationMatrix(OMOnes); const DoubleVoxelGridIndex3D doubleIndexPixelOutside1 = DoubleVoxelGridIndex3D(-0.501, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelOutside2 = DoubleVoxelGridIndex3D(0.0, 9.501, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelZero1 = DoubleVoxelGridIndex3D(0.0, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelZero2 = DoubleVoxelGridIndex3D(-0.5, -0.5, -0.5); const DoubleVoxelGridIndex3D doubleIndexPixelZero3 = DoubleVoxelGridIndex3D(0.499999, 0.499999, 0.499999); const DoubleVoxelGridIndex3D doubleIndexPixelOne1 = DoubleVoxelGridIndex3D(1.0, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelOne2 = DoubleVoxelGridIndex3D(0.5, 0.499999, 0.499999); const DoubleVoxelGridIndex3D doubleIndexPixelOne3 = DoubleVoxelGridIndex3D(1.49, -0.5, -0.5); const DoubleVoxelGridIndex3D doubleIndexPixelLast1 = DoubleVoxelGridIndex3D(9.0, 9.0, 9.0); const DoubleVoxelGridIndex3D doubleIndexPixelLast2 = DoubleVoxelGridIndex3D(9.4999, 9.4999, 9.4999); const DoubleVoxelGridIndex3D doubleIndexPixelLast3 = DoubleVoxelGridIndex3D(8.501, 8.501, 8.501); const VoxelGridIndex3D indexPixelOutside = VoxelGridIndex3D(11, 0, 0); const VoxelGridIndex3D indexPixelZero = VoxelGridIndex3D(0, 0, 0); const VoxelGridIndex3D indexPixelOne = VoxelGridIndex3D(1, 0, 0); const VoxelGridIndex3D indexPixelLast = VoxelGridIndex3D(9, 9, 9); const WorldCoordinate3D worldCoordinateOutside1(doubleIndexPixelOutside1(0), doubleIndexPixelOutside1(1), doubleIndexPixelOutside1(2)); const WorldCoordinate3D worldCoordinateOutside2(doubleIndexPixelOutside2(0), doubleIndexPixelOutside2(1), doubleIndexPixelOutside2(2)); const WorldCoordinate3D worldCoordinatePixelZero1(doubleIndexPixelZero1(0), doubleIndexPixelZero1(1), doubleIndexPixelZero1(2)); const WorldCoordinate3D worldCoordinatePixelZero2(doubleIndexPixelZero2(0), doubleIndexPixelZero2(1), doubleIndexPixelZero2(2)); const WorldCoordinate3D worldCoordinatePixelZero3(doubleIndexPixelZero3(0), doubleIndexPixelZero3(1), doubleIndexPixelZero3(2)); const WorldCoordinate3D worldCoordinatePixelOne1(doubleIndexPixelOne1(0), doubleIndexPixelOne1(1), doubleIndexPixelOne1(2)); const WorldCoordinate3D worldCoordinatePixelOne2(doubleIndexPixelOne2(0), doubleIndexPixelOne2(1), doubleIndexPixelOne2(2)); const WorldCoordinate3D worldCoordinatePixelOne3(doubleIndexPixelOne3(0), doubleIndexPixelOne3(1), doubleIndexPixelOne3(2)); const WorldCoordinate3D worldCoordinatePixelLast1(doubleIndexPixelLast1(0), doubleIndexPixelLast1(1), doubleIndexPixelLast1(2)); const WorldCoordinate3D worldCoordinatePixelLast2(doubleIndexPixelLast2(0), doubleIndexPixelLast2(1), doubleIndexPixelLast2(2)); const WorldCoordinate3D worldCoordinatePixelLast3(doubleIndexPixelLast3(0), doubleIndexPixelLast3(1), doubleIndexPixelLast3(2)); bool isInside; isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOutside1, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOutside2, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero3); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne3); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinateOutside1, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinateOutside2, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelLast1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelLast2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelLast3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast3); CHECK(isInside); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelOutside, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelZero, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero1); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelOne, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne1); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelLast, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast1); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinateOutside1, testIntIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinateOutside2, testIntIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); //13) test getNumberOfVoxels CHECK_EQUAL(expectedVoxelDims(0)*expectedVoxelDims(1)*expectedVoxelDims(2), geoInfo.getNumberOfVoxels()); //14) Test convert, validID and validIndex geoInfo.setNumColumns(50); geoInfo.setNumRows(30); geoInfo.setNumSlices(40); VoxelGridIndex3D startIndex(0, 0, 0); VoxelGridID startId(0); VoxelGridIndex3D endIndex(geoInfo.getNumColumns() - 1, geoInfo.getNumRows() - 1, geoInfo.getNumSlices() - 1); VoxelGridID endId((geoInfo.getNumColumns()*geoInfo.getNumRows()*geoInfo.getNumSlices()) - 1); VoxelGridIndex3D indexInvalid(geoInfo.getNumColumns(), geoInfo.getNumRows(), geoInfo.getNumSlices()); VoxelGridID idInvalid(geoInfo.getNumColumns()*geoInfo.getNumRows()*geoInfo.getNumSlices()); CHECK(geoInfo.validID(startId)); CHECK(geoInfo.validIndex(startIndex)); VoxelGridIndex3D aIndex; VoxelGridID aId; CHECK(geoInfo.convert(startIndex, aId)); CHECK(geoInfo.convert(startId, aIndex)); CHECK_EQUAL(aId, startId); CHECK_EQUAL(aIndex, startIndex); CHECK(geoInfo.validID(endId)); CHECK(geoInfo.validIndex(endIndex)); CHECK(geoInfo.convert(endIndex, aId)); CHECK(geoInfo.convert(endId, aIndex)); CHECK_EQUAL(aId, endId); CHECK_EQUAL(aIndex, endIndex); CHECK(!geoInfo.validID(idInvalid)); CHECK(!geoInfo.validIndex(indexInvalid)); CHECK(!geoInfo.convert(idInvalid, aIndex)); CHECK(!geoInfo.convert(indexInvalid, aId)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/MaskVoxelTest.cpp b/testing/core/MaskVoxelTest.cpp index db593bd..38f4351 100644 --- a/testing/core/MaskVoxelTest.cpp +++ b/testing/core/MaskVoxelTest.cpp @@ -1,95 +1,94 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbMaskVoxel.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief MaskVoxelTest - test the API of MaskVoxel 1) test constructors (values as expected?) 2) test set/getRelevantVolumeFraction 3) test operators "==" 4) test operator "<" */ int MaskVoxelTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) test constructors (values as expected?) //MaskVoxel(const VoxelGridID& aVoxelGridID); VoxelGridID anID = 5; const FractionType defaultFraction = 1; CHECK_NO_THROW(core::MaskVoxel MaskVoxel(anID)); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID), core::InvalidParameterException); core::MaskVoxel aMaskVoxel2(anID); CHECK_EQUAL(anID, aMaskVoxel2.getVoxelGridID()); CHECK_EQUAL(defaultFraction, aMaskVoxel2.getRelevantVolumeFraction()); //MaskVoxel(const VoxelGridID& aVoxelGridID, FractionType aVolumeFraction) anID = 15; FractionType aFraction = 0.73; CHECK_NO_THROW(core::MaskVoxel MaskVoxel(anID, aFraction)); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(anID, -aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, -aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(anID, aFraction + 2), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, aFraction + 2), core::InvalidParameterException); core::MaskVoxel aMaskVoxel3(anID, aFraction); CHECK_EQUAL(anID, aMaskVoxel3.getVoxelGridID()); CHECK_EQUAL(aFraction, aMaskVoxel3.getRelevantVolumeFraction()); //2) test set/getRelevantVolumeFraction aFraction = 0.42; anID = aMaskVoxel3.getVoxelGridID(); CHECK_NO_THROW(aMaskVoxel3.setRelevantVolumeFraction(aFraction)); CHECK_THROW_EXPLICIT(aMaskVoxel3.setRelevantVolumeFraction(-aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(aMaskVoxel3.setRelevantVolumeFraction(aFraction + 2), core::InvalidParameterException); aMaskVoxel3.setRelevantVolumeFraction(aFraction); CHECK_EQUAL(anID, aMaskVoxel3.getVoxelGridID()); CHECK_EQUAL(aFraction, aMaskVoxel3.getRelevantVolumeFraction()); //3) test operators "==" CHECK(!(aMaskVoxel2 == aMaskVoxel3)); //not equal core::MaskVoxel aMaskVoxel4(aMaskVoxel3.getVoxelGridID()); CHECK(!(aMaskVoxel4 == aMaskVoxel3)); //equal ID, but unequal volume fraction -> not equal aMaskVoxel4.setRelevantVolumeFraction(aMaskVoxel3.getRelevantVolumeFraction()); CHECK_EQUAL(aMaskVoxel4, aMaskVoxel3); //equal aMaskVoxel2.setRelevantVolumeFraction(aMaskVoxel3.getRelevantVolumeFraction()); CHECK(!(aMaskVoxel2 == aMaskVoxel3)); //no equal ID -> not equal //4) test operator "<" core::MaskVoxel aMaskVoxel5(2); CHECK(aMaskVoxel2 < aMaskVoxel3); CHECK(!(aMaskVoxel3 < aMaskVoxel4)); CHECK(!(aMaskVoxel4 < aMaskVoxel5)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/StrVectorStructureSetGeneratorTest.cpp b/testing/core/StrVectorStructureSetGeneratorTest.cpp index 1b9c23b..8bc2dc6 100644 --- a/testing/core/StrVectorStructureSetGeneratorTest.cpp +++ b/testing/core/StrVectorStructureSetGeneratorTest.cpp @@ -1,89 +1,87 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include "litCheckMacros.h" -#include "rttbBaseType.h" #include "rttbStrVectorStructureSetGenerator.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" #include "rttbInvalidParameterException.h" -#include "rttbStructure.h" namespace rttb { namespace testing { /*! @brief StrVectorStructureSetGeneratorTest - tests the API for Structure 1) empty structure vector 2) dummy structure 3) with regex */ int StrVectorStructureSetGeneratorTest(int argc, char* argv[]) { typedef core::Structure::Pointer StructTypePointer; PREPARE_DEFAULT_TEST_REPORTING; //1) empty structure vector std::vector strVector; CHECK_NO_THROW(core::StrVectorStructureSetGenerator generator1(strVector)); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()); CHECK_EQUAL(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getNumberOfStructures(), 0); CHECK_THROW_EXPLICIT(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getStructure(0), core::InvalidParameterException); //2) dummy structure boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); StructTypePointer rectStrPtr = boost::make_shared(rect); rectStrPtr->setLabel("test"); strVector.push_back(rectStrPtr); CHECK_NO_THROW(core::StrVectorStructureSetGenerator generator2(strVector)); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()); CHECK_EQUAL(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getNumberOfStructures(), 1); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()->getStructure( 0)); //3) with regex StructTypePointer rectStrPtr2 = boost::make_shared(rect); rectStrPtr2->setLabel("none"); strVector.push_back(rectStrPtr2); core::StrVectorStructureSetGenerator generator(strVector); generator.setStructureLabelFilterActive(true); generator.setFilterRegEx("test"); CHECK_NO_THROW(generator.generateStructureSet()); CHECK_EQUAL(generator.generateStructureSet()->getNumberOfStructures(), 1); CHECK_EQUAL(generator.generateStructureSet()->getStructure(0)->getLabel(), "test"); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/core/StructureSetTest.cpp b/testing/core/StructureSetTest.cpp index 0a3932f..a79e06f 100644 --- a/testing/core/StructureSetTest.cpp +++ b/testing/core/StructureSetTest.cpp @@ -1,76 +1,75 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include "litCheckMacros.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" #include "rttbInvalidParameterException.h" -#include "rttbStructure.h" #include "rttbStructureSet.h" namespace rttb { namespace testing { /*! @brief StructureSet - tests the API for StructureSet 1) constructor 2) getters */ int StructureSetTest(int argc, char* argv[]) { typedef core::Structure::Pointer StructTypePointer; PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); StructTypePointer rectStrPtr = boost::make_shared(rect); rectStrPtr->setLabel("test"); StructTypePointer rectStrPtr2 = boost::make_shared(rect); rectStrPtr2->setLabel("test2"); const IDType patientUID("patientUID"); const IDType UID("UID"); //1) constructor CHECK_NO_THROW(core::StructureSet({ })); core::StructureSet structureSetDefault({ }); CHECK_NO_THROW(core::StructureSet({ rectStrPtr, rectStrPtr2 }, patientUID, UID)); core::StructureSet structureSet({rectStrPtr, rectStrPtr2}, patientUID, UID); //2) getters CHECK_EQUAL(structureSetDefault.getNumberOfStructures(), 0); CHECK_EQUAL(structureSet.getNumberOfStructures(), 2); CHECK_EQUAL(structureSet.getStructure(0)->getLabel(), "test"); CHECK_EQUAL(structureSet.getStructure(1)->getLabel(), "test2"); CHECK_THROW_EXPLICIT(structureSet.getStructure(2), core::InvalidParameterException); CHECK_EQUAL(structureSet.getUID(), UID); CHECK_EQUAL(structureSet.getPatientUID(), patientUID); CHECK_NO_THROW(structureSetDefault.getUID()); CHECK_NO_THROW(structureSetDefault.getPatientUID()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/core/StructureTest.cpp b/testing/core/StructureTest.cpp index 59827e1..b2ce410 100644 --- a/testing/core/StructureTest.cpp +++ b/testing/core/StructureTest.cpp @@ -1,132 +1,129 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbStructure.h" -#include "rttbInvalidParameterException.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" namespace rttb { namespace testing { /*! @brief StructureTest - tests the API for Structure 1) constructors 2) get/setXX */ int StructureTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); //1) constructors CHECK_NO_THROW(core::Structure()); core::Structure emptyTestStruct; CHECK_EQUAL("", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.getUID()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); CHECK_NO_THROW(core::Structure(rect.getStructureVector())); core::Structure rect2 = core::Structure(rect.getStructureVector()); CHECK_EQUAL(rect.getLabel(), rect2.getLabel()); CHECK(rect.getUID() != rect2.getUID()); PolygonSequenceType rectVec = rect.getStructureVector(); PolygonSequenceType rect2Vec = rect2.getStructureVector(); CHECK_EQUAL(rectVec.size(), rect2Vec.size()); PolygonSequenceType::iterator it = rectVec.begin(); PolygonSequenceType::iterator it2 = rect2Vec.begin(); for (; it != rectVec.end(); ++it) { CHECK_EQUAL(it->size(), it2->size()); PolygonType::iterator pit = it->begin(); PolygonType::iterator pit2 = it2->begin(); for (; pit != it->end(); ++pit) { CHECK_EQUAL(*(pit), *(pit2)); ++pit2; } ++it2; } CHECK_NO_THROW(core::Structure rect3 = rect); core::Structure rect3 = rect; CHECK_EQUAL(rect.getLabel(), rect3.getLabel()); CHECK_EQUAL(rect.getUID(), rect3.getUID()); PolygonSequenceType rect3Vec = rect3.getStructureVector(); CHECK_EQUAL(rectVec.size(), rect3Vec.size()); it = rectVec.begin(); PolygonSequenceType::iterator it3 = rect3Vec.begin(); for (; it != rectVec.end(); ++it) { CHECK_EQUAL(it->size(), it3->size()); PolygonType::iterator pit = it->begin(); PolygonType::iterator pit3 = it3->begin(); for (; pit != it->end(); ++pit) { CHECK_EQUAL(*(pit), *(pit3)); ++pit3; } ++it3; } //2) get/setXX CHECK_EQUAL("", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.setLabel("NEW Label")); CHECK_EQUAL("NEW Label", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.getUID()); CHECK_NO_THROW(emptyTestStruct.setUID("1.2.345.67.8.9")); CHECK_EQUAL("1.2.345.67.8.9", emptyTestStruct.getUID()); CHECK((emptyTestStruct.getStructureVector()).empty()); CHECK_EQUAL(0, emptyTestStruct.getNumberOfEndpoints()); CHECK_EQUAL(4, rect.getNumberOfEndpoints()); CHECK_EQUAL(rect.getNumberOfEndpoints(), rect2.getNumberOfEndpoints()); core::Structure circ = myStructGenerator.CreateTestStructureCircle(zPlane); CHECK_EQUAL(4004, circ.getNumberOfEndpoints()); core::Structure multiPoly = myStructGenerator.CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(zPlane, zPlane + 1); CHECK_EQUAL(8, multiPoly.getNumberOfEndpoints()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/RTBioModelExampleTest.cpp b/testing/examples/RTBioModelExampleTest.cpp index 9a99dc7..c841420 100644 --- a/testing/examples/RTBioModelExampleTest.cpp +++ b/testing/examples/RTBioModelExampleTest.cpp @@ -1,409 +1,405 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include "litCheckMacros.h" -#include "rttbBioModel.h" -#include "rttbDVH.h" #include "rttbTCPLQModel.h" #include "rttbNTCPLKBModel.h" #include "rttbNTCPRSModel.h" -#include "rttbBioModelScatterPlots.h" #include "rttbBioModelCurve.h" #include "rttbDvhBasedModels.h" -#include "rttbDoseIteratorInterface.h" #include "rttbDVHXMLFileReader.h" namespace rttb { namespace testing { /*! @brief RTBioModelTest. TCP calculated using a DVH PTV and LQ Model. NTCP tested using 3 Normal Tissue DVHs and LKB/RS Model. Test if calculation in new architecture returns similar results to the original implementation. WARNING: The values for comparison need to be adjusted if the input files are changed! */ int RTBioModelExampleTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef rttb::models::CurveDataType CurveDataType; typedef std::multimap > ScatterPlotType; typedef core::DVH::Pointer DVHPointer; //increased accuracy requires double values in the calculation (rttbBaseType.h) double toleranceEUD = 1e-5; double tolerance = 1e-7; //ARGUMENTS: 1: ptv dvh file name // 2: normal tissue 1 dvh file name // 3: normal tissue 2 dvh file name // 4: normal tissue 3 dvh file name //...........5: Virtuos MPM_LR_ah dvh lung file name //...........6: Virtuos MPM_LR_ah dvh target file name std::string DVH_FILENAME_PTV; std::string DVH_FILENAME_NT1; std::string DVH_FILENAME_NT2; std::string DVH_FILENAME_NT3; std::string DVH_FILENAME_TV_TEST; std::string DVH_Virtuos_Target; std::string DVH_Virtuos_Lung; if (argc > 1) { DVH_FILENAME_PTV = argv[1]; } if (argc > 2) { DVH_FILENAME_NT1 = argv[2]; } if (argc > 3) { DVH_FILENAME_NT2 = argv[3]; } if (argc > 4) { DVH_FILENAME_NT3 = argv[4]; } if (argc > 5) { DVH_FILENAME_TV_TEST = argv[5]; } if (argc > 6) { DVH_Virtuos_Lung = argv[6]; } if (argc > 7) { DVH_Virtuos_Target = argv[7]; } //DVH PTV rttb::io::other::DVHXMLFileReader dvhReader = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_PTV); DVHPointer dvhPtr = dvhReader.generateDVH(); CHECK_CLOSE(6.04759613161786830000e+001, models::getEUD(dvhPtr, 10), toleranceEUD); rttb::io::other::DVHXMLFileReader dvhReader_test_tv = rttb::io::other::DVHXMLFileReader( DVH_FILENAME_TV_TEST); DVHPointer dvh_test_tv = dvhReader_test_tv.generateDVH(); //test TCP LQ Model models::BioModelParamType alpha = 0.35; models::BioModelParamType beta = 0.023333333333333; models::BioModelParamType roh = 10000000; int numFractions = 2; DoseTypeGy normalizationDose = 68; rttb::models::TCPLQModel tcplq = rttb::models::TCPLQModel(dvhPtr, alpha, beta, roh, numFractions); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alpha / beta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); CHECK_NO_THROW(tcplq.init()); if (tcplq.init()) { CHECK_CLOSE(1.00497232941856940000e-127, tcplq.getValue(), tolerance); } CurveDataType curve = models::getCurveDoseVSBioModel(tcplq, normalizationDose); CurveDataType::iterator it; for (it = curve.begin(); it != curve.end(); ++it) { if ((*it).first < 72) { CHECK_EQUAL(0, (*it).second); } else if ((*it).first > 150) { CHECK((*it).second > 0.9); } } models::BioModelParamType alphaBeta = 10; tcplq.setParameters(alpha, alphaBeta, roh, 0.08); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alphaBeta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); if (tcplq.init()) { CHECK_CLOSE(1.84e-005, tcplq.getValue(), tolerance); } normalizationDose = 40; curve = models::getCurveDoseVSBioModel(tcplq, normalizationDose); alpha = 1; alphaBeta = 14.5; tcplq.setAlpha(alpha); tcplq.setAlphaBeta(alphaBeta); tcplq.setRho(roh); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alphaBeta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); if (tcplq.init()) { CHECK_CLOSE(0.954885, tcplq.getValue(), toleranceEUD); } alpha = 0.9; alphaBeta = 1; tcplq.setAlpha(alpha); tcplq.setAlphaBeta(alphaBeta); tcplq.setRho(roh); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alphaBeta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); if (tcplq.init()) { CHECK_EQUAL(1, tcplq.getValue()); } //TCP LQ Test alpha = 0.3; beta = 0.03; roh = 10000000; numFractions = 20; rttb::models::TCPLQModel tcplq_test = rttb::models::TCPLQModel(dvh_test_tv, alpha, beta, roh, numFractions); CHECK_EQUAL(alpha, tcplq_test.getAlphaMean()); CHECK_EQUAL(alpha / beta, tcplq_test.getAlphaBeta()); CHECK_EQUAL(roh, tcplq_test.getRho()); CHECK_NO_THROW(tcplq_test.init()); if (tcplq_test.init()) { CHECK_CLOSE(9.79050278878883180000e-001, tcplq_test.getValue(), tolerance); } normalizationDose = 60; curve = models::getCurveDoseVSBioModel(tcplq_test, normalizationDose); //DVH HT 1 rttb::io::other::DVHXMLFileReader dvhReader2 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT1); DVHPointer dvhPtr2 = dvhReader2.generateDVH(); CHECK_CLOSE(1.07920836034015810000e+001, models::getEUD(dvhPtr2, 10), toleranceEUD); //test RTNTCPLKBModel rttb::models::NTCPLKBModel lkb = rttb::models::NTCPLKBModel(); models::BioModelParamType aVal = 10; models::BioModelParamType mVal = 0.16; models::BioModelParamType d50Val = 55; CHECK_EQUAL(0, lkb.getA()); CHECK_EQUAL(0, lkb.getM()); CHECK_EQUAL(0, lkb.getD50()); lkb.setDVH(dvhPtr2); CHECK_EQUAL(dvhPtr2, lkb.getDVH()); lkb.setA(aVal); CHECK_EQUAL(aVal, lkb.getA()); lkb.setM(mVal); CHECK_EQUAL(mVal, lkb.getM()); lkb.setD50(d50Val); CHECK_EQUAL(d50Val, lkb.getD50()); CHECK_NO_THROW(lkb.init()); if (lkb.init()) { CHECK_CLOSE(2.53523522831366570000e-007, lkb.getValue(), tolerance); } //test RTNTCPRSModel rttb::models::NTCPRSModel rs = rttb::models::NTCPRSModel(); models::BioModelParamType gammaVal = 1.7; models::BioModelParamType sVal = 1; CHECK_EQUAL(0, rs.getGamma()); CHECK_EQUAL(0, rs.getS()); CHECK_EQUAL(0, rs.getD50()); rs.setDVH(dvhPtr2); CHECK_EQUAL(dvhPtr2, rs.getDVH()); rs.setD50(d50Val); CHECK_EQUAL(d50Val, rs.getD50()); rs.setGamma(gammaVal); CHECK_EQUAL(gammaVal, rs.getGamma()); rs.setS(sVal); CHECK_EQUAL(sVal, rs.getS()); CHECK_NO_THROW(rs.init()); if (rs.init()) { CHECK_CLOSE(3.70385888626145740000e-009, rs.getValue(), tolerance); } //DVH HT 2 rttb::io::other::DVHXMLFileReader dvhReader3 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT2); DVHPointer dvhPtr3 = dvhReader3.generateDVH(); CHECK_CLOSE(1.26287047025885110000e+001, models::getEUD(dvhPtr3, 10), toleranceEUD); //test RTNTCPLKBModel aVal = 10; mVal = 0.16; d50Val = 55; lkb.setDVH(dvhPtr3); CHECK_EQUAL(dvhPtr3, lkb.getDVH()); lkb.setA(aVal); CHECK_EQUAL(aVal, lkb.getA()); lkb.setM(mVal); CHECK_EQUAL(mVal, lkb.getM()); lkb.setD50(d50Val); CHECK_EQUAL(d50Val, lkb.getD50()); if (lkb.init()) { CHECK_CLOSE(7.36294657754956700000e-007, lkb.getValue(), tolerance); } //test RTNTCPRSModel rs = rttb::models::NTCPRSModel(); gammaVal = 1.7; sVal = 1; CHECK_EQUAL(0, rs.getGamma()); CHECK_EQUAL(0, rs.getS()); CHECK_EQUAL(0, rs.getD50()); rs.setDVH(dvhPtr3); CHECK_EQUAL(dvhPtr3, rs.getDVH()); rs.setD50(d50Val); CHECK_EQUAL(d50Val, rs.getD50()); rs.setGamma(gammaVal); CHECK_EQUAL(gammaVal, rs.getGamma()); rs.setS(sVal); CHECK_EQUAL(sVal, rs.getS()); if (rs.init()) { CHECK_CLOSE(1.76778795490939440000e-007, rs.getValue(), tolerance); } //DVH HT 3 rttb::io::other::DVHXMLFileReader dvhReader4 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT3); DVHPointer dvhPtr4 = dvhReader4.generateDVH(); CHECK_CLOSE(2.18212982041056310000e+001, models::getEUD(dvhPtr4, 10), toleranceEUD); //test RTNTCPLKBModel aVal = 10; mVal = 0.16; d50Val = 55; lkb.setDVH(dvhPtr4); CHECK_EQUAL(dvhPtr4, lkb.getDVH()); lkb.setA(aVal); CHECK_EQUAL(aVal, lkb.getA()); lkb.setM(mVal); CHECK_EQUAL(mVal, lkb.getM()); lkb.setD50(d50Val); CHECK_EQUAL(d50Val, lkb.getD50()); if (lkb.init()) { CHECK_CLOSE(8.15234192641929420000e-005, lkb.getValue(), tolerance); } //test RTNTCPRSModel rs = rttb::models::NTCPRSModel(); gammaVal = 1.7; sVal = 1; CHECK_EQUAL(0, rs.getGamma()); CHECK_EQUAL(0, rs.getS()); CHECK_EQUAL(0, rs.getD50()); rs.setDVH(dvhPtr4); CHECK_EQUAL(dvhPtr4, rs.getDVH()); rs.setD50(d50Val); CHECK_EQUAL(d50Val, rs.getD50()); rs.setGamma(gammaVal); CHECK_EQUAL(gammaVal, rs.getGamma()); rs.setS(sVal); CHECK_EQUAL(sVal, rs.getS()); if (rs.init()) { CHECK_CLOSE(2.02607985020919480000e-004, rs.getValue(), tolerance); } //test using Virtuos Pleuramesotheliom MPM_LR_ah //DVH PTV rttb::io::other::DVHXMLFileReader dR_Target = rttb::io::other::DVHXMLFileReader(DVH_Virtuos_Target); DVHPointer dvhPtrTarget = dR_Target.generateDVH(); rttb::io::other::DVHXMLFileReader dR_Lung = rttb::io::other::DVHXMLFileReader(DVH_Virtuos_Lung); DVHPointer dvhPtrLung = dR_Lung.generateDVH(); //test TCP LQ Model models::BioModelParamType alphaMean = 0.34; models::BioModelParamType alphaVarianz = 0.02; models::BioModelParamType alpha_beta = 28; models::BioModelParamType rho = 1200; int numFractionsVirtuos = 27; rttb::models::TCPLQModel tcplqVirtuos = rttb::models::TCPLQModel(dvhPtrTarget, rho, numFractionsVirtuos, alpha_beta, alphaMean, alphaVarianz); if (tcplqVirtuos.init()) { CHECK_CLOSE(0.8894, tcplqVirtuos.getValue(), 1e-4); } models::BioModelParamType d50Mean = 20; models::BioModelParamType m = 0.36; models::BioModelParamType a = 1.06; rttb::models::NTCPLKBModel lkbVirtuos = rttb::models::NTCPLKBModel(dvhPtrLung, d50Mean, m, a); if (lkbVirtuos.init()) { CHECK_CLOSE(0.0397, lkbVirtuos.getValue(), 1e-4); } RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/RTBioModelScatterPlotExampleTest.cpp b/testing/examples/RTBioModelScatterPlotExampleTest.cpp index 9dd4896..f8bf9e9 100644 --- a/testing/examples/RTBioModelScatterPlotExampleTest.cpp +++ b/testing/examples/RTBioModelScatterPlotExampleTest.cpp @@ -1,473 +1,469 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include "litCheckMacros.h" -#include "rttbBioModel.h" -#include "rttbDVH.h" #include "rttbTCPLQModel.h" #include "rttbNTCPLKBModel.h" #include "rttbNTCPRSModel.h" -#include "rttbBioModelScatterPlots.h" -#include "rttbBioModelCurve.h" #include "rttbDvhBasedModels.h" #include "../models/rttbScatterTester.h" #include "rttbInvalidParameterException.h" #include "rttbDVHXMLFileReader.h" namespace rttb { namespace testing { /*! @brief RTBioModelScatterPlotExampleTest. calculating Curves and Scatterplots for TCP and NTCP models. The values on curve and scatterplot need to be similar for similar dose values. The range of difference is given by the variance used to generate the scatter. WARNING: The values for comparison need to be adjusted if the input files are changed! */ int RTBioModelScatterPlotExampleTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef rttb::models::CurveDataType CurveDataType; typedef rttb::models::ScatterPlotType ScatterPlotType; typedef core::DVH::Pointer DVHPointer; //increased accuracy requires double values in the calculation (rttbBaseType.h) double toleranceEUD = 1e-5; //ARGUMENTS: 1: ptv dvh file name // 2: normal tissue 1 dvh file name // 3: TV dvh file name std::string DVH_FILENAME_PTV; std::string DVH_FILENAME_NT1; std::string DVH_FILENAME_TV_TEST; if (argc > 1) { DVH_FILENAME_PTV = argv[1]; } if (argc > 2) { DVH_FILENAME_NT1 = argv[2]; } if (argc > 3) { DVH_FILENAME_TV_TEST = argv[3]; } //DVH PTV rttb::io::other::DVHXMLFileReader dvhReader = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_PTV); DVHPointer dvhPtr = dvhReader.generateDVH(); rttb::io::other::DVHXMLFileReader dvhReader_test_tv = rttb::io::other::DVHXMLFileReader( DVH_FILENAME_TV_TEST); DVHPointer dvh_test_tv = dvhReader_test_tv.generateDVH(); //test TCP LQ Model models::BioModelParamType alpha = 0.35; models::BioModelParamType beta = 0.023333333333333; models::BioModelParamType roh = 10000000; int numFractions = 2; DoseTypeGy normalizationDose = 68; rttb::models::TCPLQModel tcplq = rttb::models::TCPLQModel(dvhPtr, alpha, beta, roh, numFractions); CHECK_NO_THROW(tcplq.init()); CurveDataType curve = models::getCurveDoseVSBioModel(tcplq, normalizationDose); CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, 0, normalizationDose, 100)); ScatterPlotType tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 0, alpha, 0, normalizationDose, 100); CHECK_EQUAL(100, tcpScatter.size()); ScatterTester scatterCompare(curve, tcpScatter); CHECK_TESTER(scatterCompare); //test also with other parameter tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 3, roh, 0, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); CHECK_TESTER(scatterCompare); std::vector paramIdVec; models::BioModel::ParamVectorType meanVec; models::BioModel::ParamVectorType meanVecTest; meanVecTest.push_back(alpha); models::BioModel::ParamVectorType varianceVec; //"alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 paramIdVec.push_back(0); meanVec.push_back(tcplq.getAlphaMean()); varianceVec.push_back(0); //setting parameter 1 will change the resulting scatter plot dramatically - is it meant to? //this is unexpected since the value was taken from the original calculation //paramIdVec.push_back(1); meanVec.push_back(tcplq.getAlphaVariance()); varianceVec.push_back(0); paramIdVec.push_back(2); meanVec.push_back(tcplq.getAlphaBeta()); varianceVec.push_back(0); paramIdVec.push_back(3); meanVec.push_back(tcplq.getRho()); varianceVec.push_back(0); CHECK_THROW_EXPLICIT(models::getScatterPlotVaryParameters(tcplq, paramIdVec, meanVecTest, varianceVec, normalizationDose, 50), core::InvalidParameterException); ScatterPlotType scatterVary = models::getScatterPlotVaryParameters(tcplq, paramIdVec, meanVec, varianceVec, normalizationDose, 50); CHECK_EQUAL(50, scatterVary.size()); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); models::BioModelParamType variance = 0.00015; CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, variance, normalizationDose, 100)); tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 0, alpha, variance, normalizationDose, 100); scatterCompare.setVariance(variance); scatterCompare.setCompareScatter(tcpScatter); //allow 5% of the points to deviate more scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); //test also with other parameter tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 3, roh, variance, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); //allow 5% of the points to deviate more scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(tcplq.getAlphaMean()); varianceVec.push_back(variance); //paramIdVec.push_back(1); meanVec.push_back(tcplq.getAlphaVariance()); varianceVec.push_back(variance); paramIdVec.push_back(2); meanVec.push_back(tcplq.getAlphaBeta()); varianceVec.push_back(variance); paramIdVec.push_back(3); meanVec.push_back(tcplq.getRho()); varianceVec.push_back(variance); scatterVary = models::getScatterPlotVaryParameters(tcplq, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); //allow 5% of the points to deviate more scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); models::BioModelParamType alphaBeta = 10; tcplq.setParameters(alpha, alphaBeta, roh, 0.08); tcplq.init(); normalizationDose = 40; curve = models::getCurveDoseVSBioModel(tcplq, normalizationDose); CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, 0, normalizationDose, 100)); tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 0, alpha, 0, normalizationDose, 100); scatterCompare.setReferenceCurve(curve); scatterCompare.setVariance(0); //do not allow larger deviations scatterCompare.setAllowExceptions(false); scatterCompare.setCompareScatter(tcpScatter); CHECK_TESTER(scatterCompare); variance = 0.25; CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, variance, normalizationDose, 100)); tcpScatter = models::getScatterPlotVary1Parameter(tcplq, 0, alpha, variance, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); scatterCompare.setVariance(variance); //allow 5% of the points to deviate more scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); /*TCP LQ Test*/ alpha = 0.3; beta = 0.03; roh = 10000000; numFractions = 20; rttb::models::TCPLQModel tcplq_test = rttb::models::TCPLQModel(dvh_test_tv, alpha, beta, roh, numFractions); CHECK_NO_THROW(tcplq_test.init()); normalizationDose = 60; curve = models::getCurveDoseVSBioModel(tcplq_test, normalizationDose); CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq_test, 0, alpha, 0, normalizationDose, 100)); tcpScatter = models::getScatterPlotVary1Parameter(tcplq_test, 0, alpha, 0, normalizationDose, 100); scatterCompare.setReferenceCurve(curve); scatterCompare.setVariance(0); scatterCompare.setCompareScatter(tcpScatter); CHECK_TESTER(scatterCompare); //test also with other parameter tcpScatter = models::getScatterPlotVary1Parameter(tcplq_test, 3, roh, 0, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(tcplq_test.getAlphaMean()); varianceVec.push_back(0); //paramIdVec.push_back(1); meanVec.push_back(tcplq_test.getAlphaVariance()); varianceVec.push_back(0); paramIdVec.push_back(2); meanVec.push_back(tcplq_test.getAlphaBeta()); varianceVec.push_back(0); paramIdVec.push_back(3); meanVec.push_back(tcplq_test.getRho()); varianceVec.push_back(0); scatterVary = models::getScatterPlotVaryParameters(tcplq_test, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); variance = 0.00025; CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq_test, 0, alpha, variance, normalizationDose, 100)); tcpScatter = models::getScatterPlotVary1Parameter(tcplq_test, 0, alpha, variance, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); scatterCompare.setVariance(variance); CHECK_TESTER(scatterCompare); //test also with other parameter tcpScatter = models::getScatterPlotVary1Parameter(tcplq_test, 3, roh, variance, normalizationDose, 100); scatterCompare.setCompareScatter(tcpScatter); scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); scatterCompare.setAllowExceptions(false); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(tcplq_test.getAlphaMean()); varianceVec.push_back(variance); //paramIdVec.push_back(1); meanVec.push_back(tcplq_test.getAlphaVariance()); varianceVec.push_back(variance); paramIdVec.push_back(2); meanVec.push_back(tcplq_test.getAlphaBeta()); varianceVec.push_back(variance); paramIdVec.push_back(3); meanVec.push_back(tcplq_test.getRho()); varianceVec.push_back(variance); scatterVary = models::getScatterPlotVaryParameters(tcplq_test, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); //allow 5% of the points to deviate more scatterCompare.setAllowExceptions(true); CHECK_TESTER(scatterCompare); //DVH HT 1 rttb::io::other::DVHXMLFileReader dvhReader2 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT1); DVHPointer dvhPtr2 = dvhReader2.generateDVH(); CHECK_CLOSE(1.07920836034015810000e+001, models::getEUD(dvhPtr2, 10), toleranceEUD); //test RTNTCPLKBModel rttb::models::NTCPLKBModel lkb = rttb::models::NTCPLKBModel(); models::BioModelParamType aVal = 10; models::BioModelParamType mVal = 0.16; models::BioModelParamType d50Val = 55; lkb.setDVH(dvhPtr2); lkb.setA(aVal); lkb.setM(mVal); lkb.setD50(d50Val); CHECK_NO_THROW(lkb.init()); normalizationDose = 60; curve = models::getCurveDoseVSBioModel(lkb, normalizationDose); CHECK_NO_THROW(models::getScatterPlotVary1Parameter(lkb, 2, aVal, 0, normalizationDose, 100)); ScatterPlotType scatter = models::getScatterPlotVary1Parameter(lkb, 2, aVal, 0, normalizationDose, 100); scatterCompare.setReferenceCurve(curve); scatterCompare.setVariance(0); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); //"d50":0,"m":1,"a":2 //test also with other parameter scatter = models::getScatterPlotVary1Parameter(lkb, 0, d50Val, 0, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(lkb.getD50()); varianceVec.push_back(0); paramIdVec.push_back(1); meanVec.push_back(lkb.getM()); varianceVec.push_back(0); paramIdVec.push_back(2); meanVec.push_back(lkb.getA()); varianceVec.push_back(0); scatterVary = models::getScatterPlotVaryParameters(lkb, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); variance = 0.00025; CHECK_NO_THROW(models::getScatterPlotVary1Parameter(lkb, 2, aVal, variance, normalizationDose, 100)); scatter = models::getScatterPlotVary1Parameter(lkb, 2, aVal, variance, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); scatterCompare.setVariance(variance); CHECK_TESTER(scatterCompare); //test also with other parameter scatter = models::getScatterPlotVary1Parameter(lkb, 0, d50Val, variance, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(lkb.getD50()); varianceVec.push_back(variance); paramIdVec.push_back(1); meanVec.push_back(lkb.getM()); varianceVec.push_back(variance); paramIdVec.push_back(2); meanVec.push_back(lkb.getA()); varianceVec.push_back(variance); scatterVary = models::getScatterPlotVaryParameters(lkb, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); //test RTNTCPRSModel rttb::models::NTCPRSModel rs = rttb::models::NTCPRSModel(); models::BioModelParamType gammaVal = 1.7; models::BioModelParamType sVal = 1; rs.setDVH(dvhPtr2); rs.setD50(d50Val); rs.setGamma(gammaVal); rs.setS(sVal); CHECK_NO_THROW(rs.init()); normalizationDose = 60; curve = models::getCurveDoseVSBioModel(rs, normalizationDose); CHECK_NO_THROW(models::getScatterPlotVary1Parameter(rs, 0, d50Val, 0, normalizationDose, 100)); scatter = models::getScatterPlotVary1Parameter(rs, 0, d50Val, 0, normalizationDose, 100); scatterCompare.setReferenceCurve(curve); scatterCompare.setVariance(0); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); //"d50":0,"gamma":1,"s":2 //test also with other parameter scatter = models::getScatterPlotVary1Parameter(rs, 1, gammaVal, 0, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(rs.getD50()); varianceVec.push_back(0); paramIdVec.push_back(1); meanVec.push_back(rs.getGamma()); varianceVec.push_back(0); paramIdVec.push_back(2); meanVec.push_back(rs.getS()); varianceVec.push_back(0); scatterVary = models::getScatterPlotVaryParameters(rs, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); variance = 0.0075; CHECK_NO_THROW(models::getScatterPlotVary1Parameter(rs, 0, d50Val, variance, normalizationDose, 100)); scatter = models::getScatterPlotVary1Parameter(rs, 0, d50Val, variance, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); scatterCompare.setVariance(variance); CHECK_TESTER(scatterCompare); //test also with other parameter scatter = models::getScatterPlotVary1Parameter(rs, 2, sVal, variance, normalizationDose, 100); scatterCompare.setCompareScatter(scatter); CHECK_TESTER(scatterCompare); paramIdVec.clear(); meanVec.clear(); varianceVec.clear(); paramIdVec.push_back(0); meanVec.push_back(rs.getD50()); varianceVec.push_back(variance); paramIdVec.push_back(1); meanVec.push_back(rs.getGamma()); varianceVec.push_back(variance); paramIdVec.push_back(2); meanVec.push_back(rs.getS()); varianceVec.push_back(variance); scatterVary = models::getScatterPlotVaryParameters(rs, paramIdVec, meanVec, varianceVec, normalizationDose, 50); scatterCompare.setCompareScatter(scatterVary); CHECK_TESTER(scatterCompare); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/RTDVHTest.cpp b/testing/examples/RTDVHTest.cpp index 8b7e18d..8e48c2a 100644 --- a/testing/examples/RTDVHTest.cpp +++ b/testing/examples/RTDVHTest.cpp @@ -1,101 +1,99 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include "litCheckMacros.h" -#include "rttbDVH.h" -#include "rttbBaseType.h" #include "rttbDvhBasedModels.h" #include "rttbDVHXMLFileReader.h" namespace rttb { namespace testing { /*! @brief RTDVHTest. Max, min, mean, modal, median, Vx, Dx, EUD, BED, LQED2 are tested. Test if calculation in new architecture returns similar results to the original implementation. Comparison of actual DVH values is performed in DVHCalculatorComparisonTest.cpp. WARNING: The values for comparison need to be adjusted if the input files are changed! */ int RTDVHTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: dvh file name std::string RTDVH_FILENAME_PTV; if (argc > 1) { RTDVH_FILENAME_PTV = argv[1]; } /*test RT dvh*/ rttb::io::other::DVHXMLFileReader dvhReader = rttb::io::other::DVHXMLFileReader(RTDVH_FILENAME_PTV); const DoseCalcType expectedValue = 0.01305; //dvhReader core::DVH::Pointer dvh = dvhReader.generateDVH(); CHECK_CLOSE(expectedValue, models::getEUD(dvh, 10), errorConstant); std::cout << models::getEUD(dvh, 10) << std::endl; CHECK_NO_THROW(models::calcBEDDVH(dvh, 15, 15)); CHECK_NO_THROW(models::calcLQED2DVH(dvh, 15, 10)); CHECK_NO_THROW(dvh->getDataDifferential()); CHECK_EQUAL(1, dvh->convertAbsoluteToRelative().at(0)); CHECK_NO_THROW(models::calcBEDDVH(dvh, 15, 15, true)); CHECK_NO_THROW(models::calcLQED2DVH(dvh, 15, 10, true)); //test statistics (relative cumulative data) CHECK_CLOSE(expectedValue, dvh->getMaximum(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMinimum(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMean(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMedian(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getModal(), errorConstant); CHECK_EQUAL(0, dvh->getVx(0.014)); CHECK_EQUAL(250, dvh->getVx(0.01)); CHECK_CLOSE(0.0131, dvh->getDx(100), errorConstant + errorConstant * 10); CHECK_CLOSE(0.013, dvh->getDx(249), errorConstant); CHECK_EQUAL(0, dvh->getDx(251)); //test statistics (absolute cumulative data) CHECK_EQUAL(2000, dvh->getDataCumulative().at(0)); CHECK_EQUAL(0, dvh->getVx(0.014)); CHECK_EQUAL(250, dvh->getVx(0.01)); CHECK_CLOSE(0.0131, dvh->getDx(100), errorConstant + errorConstant * 10); CHECK_CLOSE(0.013, dvh->getDx(249), errorConstant); CHECK_EQUAL(0, dvh->getDx(251)); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/RTDoseIndexTest.cpp b/testing/examples/RTDoseIndexTest.cpp index 35899fc..238a7da 100644 --- a/testing/examples/RTDoseIndexTest.cpp +++ b/testing/examples/RTDoseIndexTest.cpp @@ -1,202 +1,194 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include "litCheckMacros.h" -#include "rttbDoseIndex.h" -#include "rttbDVHSet.h" -#include "rttbBaseType.h" -#include "rttbNullPointerException.h" #include "rttbConformalIndex.h" #include "rttbConformationNumber.h" #include "rttbConformityIndex.h" #include "rttbCoverageIndex.h" #include "rttbHomogeneityIndex.h" -#include "rttbException.h" #include "rttbInvalidParameterException.h" #include "rttbDVHXMLFileReader.h" -#include - #include -#include namespace rttb { namespace testing { /*! @brief DoseIndexTest. ConformationNumber ConformalIndex ConformityIndex CoverageIndex HomogeneityIndex are tested. test dvh: deltaV 0.125, deltaD 0.5 1. dvh TV: number of voxels 2900, maximum dose bin 133, dose bin 127~133 2. dvh HT1: number of voxels 5410, maximum dose bin 40, dose bin 0~2,40 3. dvh HT2: number of voxels 10210, maximum dose bin 50, dose bin 0~2,50 4. dvh HT3: number of voxels 1210, maximum dose bin 70, dose bin 0~2,70 Test if calculation in new architecture returns similar results to the original implementation. WARNING: The values for comparison need to be adjusted if the input files are changed! */ int RTDoseIndexTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: ptv dvh file name // 2: normal tissue 1 dvh file name // 3: normal tissue 2 dvh file name // 4: normal tissue 3 dvh file name std::string DVH_FILENAME_PTV; std::string DVH_FILENAME_NT1; std::string DVH_FILENAME_NT2; std::string DVH_FILENAME_NT3; if (argc > 1) { DVH_FILENAME_PTV = argv[1]; } if (argc > 2) { DVH_FILENAME_NT1 = argv[2]; } if (argc > 3) { DVH_FILENAME_NT2 = argv[3]; } if (argc > 4) { DVH_FILENAME_NT3 = argv[4]; } /*test dvh: deltaV 0.125, deltaD 0.5*/ /*dvh TV: number of voxels 2900, maximum dose bin 133, dose bin 127~133*/ rttb::io::other::DVHXMLFileReader dvhReader = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_PTV); rttb::core::DVH dvhPTV = *(dvhReader.generateDVH()); /*dvh HT1: number of voxels 5410, maximum dose bin 40, dose bin 0~2,40*/ rttb::io::other::DVHXMLFileReader dvhReader1 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT1); core::DVH dvhNT1 = *(dvhReader1.generateDVH()); /*dvh HT2: number of voxels 10210, maximum dose bin 50, dose bin 0~2,50*/ rttb::io::other::DVHXMLFileReader dvhReader2 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT2); core::DVH dvhNT2 = *(dvhReader2.generateDVH()); /*dvh HT3: number of voxels 1210, maximum dose bin 70, dose bin 0~2,70*/ rttb::io::other::DVHXMLFileReader dvhReader3 = rttb::io::other::DVHXMLFileReader(DVH_FILENAME_NT3); core::DVH dvhNT3 = *(dvhReader3.generateDVH()); std::vector dvhTVSet; std::vector dvhHTSet; dvhTVSet.push_back(dvhPTV); dvhHTSet.push_back(dvhNT1); dvhHTSet.push_back(dvhNT2); dvhHTSet.push_back(dvhNT3); ::boost::shared_ptr dvhSetPtr = ::boost::make_shared(dvhTVSet, dvhHTSet, "testStrSet", dvhPTV.getDoseID()); /*test exception*/ ::boost::shared_ptr dvhSetNullPtr; CHECK_THROW_EXPLICIT(indices::ConformalIndex(dvhSetNullPtr, 0), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::ConformationNumber(dvhSetNullPtr, 0), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::ConformityIndex(dvhSetNullPtr, 0), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::CoverageIndex(dvhSetNullPtr, 0), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::HomogeneityIndex(dvhSetNullPtr, 0), core::InvalidParameterException); /*test exception for invalid reference dose*/ CHECK_THROW_EXPLICIT(indices::ConformalIndex(dvhSetPtr, 100), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::ConformationNumber(dvhSetPtr, 100), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::ConformityIndex(dvhSetPtr, 100), core::InvalidParameterException); CHECK_THROW_EXPLICIT(indices::HomogeneityIndex(dvhSetPtr, 0), core::InvalidParameterException); /*test index calculation*/ /*RTConformationNumber */ //PTV covered by reference dose 30 = the whole PTV =362.5; Volume of the referece 30=362.5+1.25 indices::ConformationNumber cn = indices::ConformationNumber(dvhSetPtr, 30); //check if values are close. Equality is only achieved with double precission. CHECK_CLOSE(362.5 / 363.75, cn.getValue(), errorConstant); //cn==1*TV0/V0=362.5/2466.25 cn.setDoseReference(0); CHECK_CLOSE(362.5 / 2466.25, cn.getValue(), errorConstant); cn.setDoseReference(65); CHECK_CLOSE(2300 / 2900.0, cn.getValue(), errorConstant); //ref dose: 65 -> TVref=Vref -> cn=TVref/TV=2300/2900 CHECK_EQUAL(cn.getValue(), cn.getValueAt(0)); CHECK_THROW_EXPLICIT(cn.getValueAt(1), core::InvalidParameterException); /*ConformalIndex */ //HT 1 covered by ref=HT2 covered by ref=0, HT3 covered by ref=1.25 indices::ConformalIndex coin = indices::ConformalIndex(dvhSetPtr, 30); CHECK_CLOSE((362.5 / 363.75) * (1 - 1.25 / 151.25), coin.getValue(), errorConstant); coin.setDoseReference(0); CHECK_EQUAL(0, coin.getValue()); coin.setDoseReference(65); CHECK_CLOSE(2300 / 2900.0, coin.getValue(), errorConstant); //ref dose: 65 -> Vref=0 for all HT -> cn=cn*(1-0)=cn CHECK_EQUAL(coin.getValue(), coin.getValueAt(0)); CHECK_THROW_EXPLICIT(coin.getValueAt(1), core::InvalidParameterException); /*ConformityIndex */ indices::ConformityIndex ci = indices::ConformityIndex(dvhSetPtr, 30); CHECK_CLOSE(362.5 / 363.75, ci.getValue(), errorConstant); ci.setDoseReference(65); CHECK_CLOSE(2300 / 2900.0, ci.getValue(), errorConstant); //ref dose: 65->ci=2300/2900*1*1*1 CHECK_EQUAL(ci.getValue(), ci.getValueAt(0)); CHECK_THROW_EXPLICIT(ci.getValueAt(1), core::InvalidParameterException); /*CoverageIndex*/ indices::CoverageIndex coverageI = indices::CoverageIndex(dvhSetPtr, 30); CHECK_CLOSE(362.5 / 362.5, coverageI.getValue(), errorConstant); //ref dose: 30 -> coverage index=1 coverageI.setDoseReference(65); CHECK_CLOSE(2300 / 2900.0, coverageI.getValue(), errorConstant); //ref dose: 65->coverage index=2300/2900 CHECK_EQUAL(coverageI.getValue(), coverageI.getValueAt(0)); CHECK_THROW_EXPLICIT(coverageI.getValueAt(1), core::InvalidParameterException); /*HomogeneityIndex TV max: 133*0.5=66.5, TV min: 127*0.5=63.5 -> hi=(66.5-63.5)/30*/ indices::HomogeneityIndex hi = indices::HomogeneityIndex(dvhSetPtr, 30); CHECK_CLOSE(3 / 30.0, hi.getValue(), errorConstant); hi.setDoseReference(65); CHECK_CLOSE(3 / 65.0, hi.getValue(), errorConstant); CHECK_EQUAL(hi.getValue(), hi.getValueAt(0)); CHECK_THROW_EXPLICIT(hi.getValueAt(1), core::InvalidParameterException); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/examples/RTDoseStatisticsDicomTest.cpp b/testing/examples/RTDoseStatisticsDicomTest.cpp index d7b58c6..9a08b6c 100644 --- a/testing/examples/RTDoseStatisticsDicomTest.cpp +++ b/testing/examples/RTDoseStatisticsDicomTest.cpp @@ -1,112 +1,106 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbDoseStatistics.h" #include "rttbDoseStatisticsCalculator.h" -#include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" -#include "rttbBoostMaskAccessor.h" -#include "rttbGenericMaskedDoseIterator.h" #include "rttbGenericDoseIterator.h" -#include "rttbBaseType.h" namespace rttb { namespace testing { /*! @brief RTDoseStatisticsTest. Max, min, mean, standard deviation, variance, Vx, Dx, MOHx, MOCx, MaxOHx, MinOCx are tested. Test if calculation in new architecture returns similar results to the original implementation. WARNING: The values for comparison need to be adjusted if the input files are changed!*/ int RTDoseStatisticsDicomTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } else { std::cout << "at least one arguments required for RTDoseStatisticsDicomTest" << std::endl; return -1; } double expectedVal = 5.64477e-005; double volume = 24120.; typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::GenericDoseIterator::DoseIteratorPointer DoseIteratorPointer; typedef algorithms::DoseStatisticsCalculator::ResultListPointer ResultListPointer; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //create corresponding DoseIterator ::boost::shared_ptr spDoseIteratorTmp = ::boost::make_shared(doseAccessor1); DoseIteratorPointer spDoseIterator(spDoseIteratorTmp); rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculator(spDoseIterator); std::vector precomputedDoseValues; precomputedDoseValues.push_back(0); precomputedDoseValues.push_back(0.5); precomputedDoseValues.push_back(1); std::vector precomputedVolumeValues; precomputedVolumeValues.push_back(20000 / volume); precomputedVolumeValues.push_back(1); auto doseStatistics = doseStatisticsCalculator.calculateDoseStatistics(precomputedDoseValues, precomputedVolumeValues); CHECK_CLOSE(doseStatistics->getMean(), expectedVal, errorConstant); CHECK_CLOSE(doseStatistics->getStdDeviation(), 0, errorConstant); CHECK_CLOSE(doseStatistics->getVariance(), 0, errorConstant); double dummy; DoseTypeGy vx = doseStatistics->getVx().getValue(expectedVal, true, dummy); CHECK_EQUAL(vx, doseStatistics->getVx().getValue(0)); CHECK_CLOSE(expectedVal, doseStatistics->getDx().getValue(vx), reducedErrorConstant); CHECK_CLOSE(doseStatistics->getMaximum(), expectedVal, errorConstant); CHECK_CLOSE(doseStatistics->getMinimum(), expectedVal, errorConstant); ResultListPointer minListPtr = doseStatistics->getMinimumVoxelPositions(); ResultListPointer maxListPtr = doseStatistics->getMaximumVoxelPositions(); CHECK_EQUAL(maxListPtr->size(), 10); CHECK_EQUAL(minListPtr->size(), 10); CHECK_CLOSE(doseStatistics->getDx().getValue(24120), doseStatistics->getMinimum(), 0.001); CHECK_CLOSE(doseStatistics->getMOHx().getValue(24120), doseStatistics->getMean(), reducedErrorConstant); CHECK_CLOSE(doseStatistics->getMOCx().getValue(20000), doseStatistics->getMean(), reducedErrorConstant); CHECK_CLOSE(doseStatistics->getMinOCx().getValue(20000), doseStatistics->getMean(), reducedErrorConstant); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/rttbTestExamples.cpp b/testing/examples/rttbTestExamples.cpp index 5fb25de..08781a5 100644 --- a/testing/examples/rttbTestExamples.cpp +++ b/testing/examples/rttbTestExamples.cpp @@ -1,61 +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. // //------------------------------------------------------------------------ // 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" -#include "RTToolboxConfigure.h" - namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(RTBioModelExampleTest); LIT_REGISTER_TEST(RTDVHTest); LIT_REGISTER_TEST(RTDoseIndexTest); LIT_REGISTER_TEST(RTDoseStatisticsDicomTest); LIT_REGISTER_TEST(RTBioModelScatterPlotExampleTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (const std::exception& /*e*/) { result = -1; } catch (...) { result = -1; } return result; } diff --git a/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp b/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp index b4c184f..7f497b2 100644 --- a/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp +++ b/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp @@ -1,172 +1,167 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #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 = boost::make_shared(); auto interpolationLinear = boost::make_shared(); 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 = boost::make_shared(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 = boost::make_shared(transformITKTranslationTemporary); auto aSimpleMappableDoseAccessorITKIdentity = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear); auto aSimpleMappableDoseAccessorITKTranslation = boost::make_shared(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(nullptr), 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 (size_t 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->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKIdentity->getValueAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKIdentity->getValueAt(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 (size_t 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->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKTranslation->getValueAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKTranslation->getValueAt(currentId)); } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp b/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp index 677ce61..0a32b69 100644 --- a/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp +++ b/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp @@ -1,233 +1,227 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #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 = ::boost::make_shared(); auto interpolationLinear = ::boost::make_shared(); NearestNeighborInterpolation::Pointer interpolationNull; auto transformMP = ::boost::make_shared(registration.GetPointer()); auto aSimpleMappableDoseAccessorMPIdentityLinear = ::boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); auto aSimpleMappableDoseAccessorMPIdentityNN = ::boost::make_shared(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(nullptr), 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->getValueAt(runningID), doseAccessor2->getValueAt(runningID)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPIdentityNN->getValueAt(runningID), doseAccessor2->getValueAt(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 = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); auto aSimpleMappableDoseAccessorMPTranslationNN = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN); rttb::VoxelGridIndex3D aIndexBeforeTransformation(0, 0, 0); rttb::VoxelGridIndex3D aIndexAfterTransformation(1, 1, 1); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getValueAt(aIndexBeforeTransformation), doseAccessor2->getValueAt(aIndexAfterTransformation)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation), doseAccessor2->getValueAt(aIndexAfterTransformation)); rttb::VoxelGridIndex3D aIndexBeforeTransformation2(20, 10, 10); rttb::VoxelGridIndex3D aIndexAfterTransformation2(21, 11, 11); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getValueAt(aIndexBeforeTransformation2), doseAccessor2->getValueAt(aIndexAfterTransformation2)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation2), doseAccessor2->getValueAt(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->getValueAt(aIndexBeforeTransformation3), doseAccessor2->getValueAt(aIndexAfterTransformation3)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation3), doseAccessor2->getValueAt(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 = boost::make_shared(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 = boost::make_shared(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 (size_t i = 0; i < coordinatesToCheckX.size(); ++i) { for (size_t j = 0; j < coordinatesToCheckY.size(); ++j) { for (size_t k = 0; k < coordinatesToCheckZ.size(); ++k) { CHECK_NO_THROW(aSimpleMappableDoseAccessorRealisticScenarioLinear->getValueAt(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/InterpolationMatchPointTransformation/registrationHelper.cpp b/testing/interpolation/InterpolationMatchPointTransformation/registrationHelper.cpp index 1dfd4a5..625247a 100644 --- a/testing/interpolation/InterpolationMatchPointTransformation/registrationHelper.cpp +++ b/testing/interpolation/InterpolationMatchPointTransformation/registrationHelper.cpp @@ -1,80 +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. // //------------------------------------------------------------------------ #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "registrationHelper.h" #include "litTestImageIO.h" -#include "litImageTester.h" - -#include int setImageFileNames(std::string targetImage, std::string movingImage, bool isDirectory, AppGlobals& globals) { globals.targetImageFileName = targetImage; globals.movingImageFileName = movingImage; globals.isDirectory = isDirectory; return EXIT_SUCCESS; } int loadData(AppGlobals& globals) { if (!globals.isDirectory) { globals.spTargetImage = lit::TestImageIO::InternalImageType>::readImage( globals.targetImageFileName); } else { globals.spTargetImage = map::io::readImage (globals.targetImageFileName, map::io::ImageSeriesReadStyle::Dicom); } if (globals.spTargetImage.IsNull()) { std::cerr << "Error. Cannot load target image: " << globals.targetImageFileName << std::endl; return EXIT_FAILURE; } if (!globals.isDirectory) { globals.spMovingImage = lit::TestImageIO::InternalImageType>::readImage( globals.movingImageFileName); } else { globals.spMovingImage = map::io::readImage (globals.movingImageFileName, map::io::ImageSeriesReadStyle::Dicom); } if (globals.spMovingImage.IsNull()) { std::cerr << "Error. Cannot load moving image: " << globals.movingImageFileName << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } AppGlobals::AppGlobals() { }; \ No newline at end of file diff --git a/testing/interpolation/InterpolationTest.cpp b/testing/interpolation/InterpolationTest.cpp index 6be3f13..089e106 100644 --- a/testing/interpolation/InterpolationTest.cpp +++ b/testing/interpolation/InterpolationTest.cpp @@ -1,221 +1,218 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#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 right corner interpolation 4) 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 auto interpolationNN = boost::make_shared(); interpolationNN->setAccessorPointer(doseAccessor1); auto interpolationLinear = boost::make_shared(); interpolationLinear->setAccessorPointer(doseAccessor1); //doseAccessor2 is used as dose image. //RTDOSE_FILENAME_INCREASE_X and RTDOSE_FILENAME_CONSTANT_TWO have the same GeometricInfo auto interpolationNN2 = boost::make_shared(); interpolationNN2->setAccessorPointer(doseAccessor2); auto interpolationLinear2 = boost::make_shared(); interpolationLinear2->setAccessorPointer(doseAccessor2); auto interpolationNullNN = boost::make_shared(); auto interpolationNullLinear = boost::make_shared(); rttb::WorldCoordinate3D imagePositionPatient = doseAccessor1->getGeometricInfo().getImagePositionPatient(); rttb::SpacingVectorType3D pixelSpacing = doseAccessor1->getGeometricInfo().getSpacing(); unsigned int size[] = {doseAccessor1->getGeometricInfo().getNumColumns(), doseAccessor1->getGeometricInfo().getNumRows(), doseAccessor1->getGeometricInfo().getNumSlices()}; //Which voxels to check is irrelevant. The following three situations are checked: // - exactly in-between two voxels: v_i=(0.5*v1 + 0.5*v2) --> target 0.5 // - the middle of a voxel: v_i = 1*v1 --> target 0 (semantically equivalent with target 1 and left/right flipped) // - 10% shifted from the middle: v_i=0.1*v1 + 0.9*v2 --> target 0.9 std::vector coordinatesX; coordinatesX.push_back(imagePositionPatient.x() - (pixelSpacing.x() * 0.5)); coordinatesX.push_back(imagePositionPatient.x() + 5 * pixelSpacing.x()); coordinatesX.push_back(imagePositionPatient.x() + 9.9 * pixelSpacing.x()); std::vector coordinatesY; coordinatesY.push_back(imagePositionPatient.y() - (pixelSpacing.y() * 0.5)); coordinatesY.push_back(imagePositionPatient.y() + 5 * pixelSpacing.y()); coordinatesY.push_back(imagePositionPatient.x() + 9.9 * pixelSpacing.y()); std::vector coordinatesZ; coordinatesZ.push_back(imagePositionPatient.z() - (pixelSpacing.z() * 0.5)); coordinatesZ.push_back(imagePositionPatient.z() + 5 * pixelSpacing.z()); coordinatesZ.push_back(imagePositionPatient.z() + 9.9 * pixelSpacing.z()); std::vector coordinatesToCheck; for (unsigned int x = 0; x < coordinatesX.size(); x++) { for (unsigned int y = 0; y < coordinatesY.size(); y++) { for (unsigned int z = 0; z < coordinatesZ.size(); z++) { coordinatesToCheck.push_back(rttb::WorldCoordinate3D(coordinatesX.at(x), coordinatesY.at(y), coordinatesZ.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 positionLastInsightImageRight = rttb::WorldCoordinate3D( positionOutsideOfImageRight.x() - 0.5 * pixelSpacing.x() - 0.000001, positionOutsideOfImageRight.y() - 0.5 * pixelSpacing.y() - 0.000001, positionOutsideOfImageRight.z() - 0.5 * pixelSpacing.z() - 0.000001 ); //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] = 1.41119e-005; } else if (i < 18) { expectedDoseIncreaseXNearest[i] = 0.000141119; expectedDoseIncreaseXLinear[i] = 0.000141119; } else { expectedDoseIncreaseXNearest[i] = 0.000282239; expectedDoseIncreaseXLinear[i] = 0.000279416; } } //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) Right corner interpolation //Checks if the interpolation works at the corner without an error CHECK_NO_THROW(interpolationLinear->getValue(positionLastInsightImageRight)); //TEST 4) 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->setAccessorPointer(doseAccessorNull), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullNN->setAccessorPointer(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(boost::make_shared()); CHECK_NO_THROW(boost::make_shared()); RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/interpolation/RosuMappableDoseAccessorTest.cpp b/testing/interpolation/RosuMappableDoseAccessorTest.cpp index 6dac371..c6299f2 100644 --- a/testing/interpolation/RosuMappableDoseAccessorTest.cpp +++ b/testing/interpolation/RosuMappableDoseAccessorTest.cpp @@ -1,144 +1,140 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include -#include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbRosuMappableDoseAccessor.h" - #include "DummyTransformation.h" - -#include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::RosuMappableDoseAccessor RosuMappableDoseAccessor; typedef rttb::interpolation::TransformationInterface TransformationInterface; /*! @brief RosuMappableDoseAccessorTest - test the API of RosuMappableDoseAccessor 1) Constructor 2) test getDoseAt() */ int RosuMappableDoseAccessorTest(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 RosuMappableDoseAccessorTest 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()); DoseAccessorPointer doseAccessorNull; auto transformDummy = boost::make_shared(); TransformationInterface::Pointer transformNull; auto aRosuMappableDoseAccessorDefault = boost::make_shared(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy); auto aRosuMappableDoseAccessorNoPadding = boost::make_shared(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, false); //1) Constructor CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy)); CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, false)); CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, true, 5.0)); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformDummy), core::NullPointerException); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformNull), core::NullPointerException); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformNull), core::NullPointerException); //2) test getDoseAt() std::vector voxelsAsIndexToTest; std::vector voxelsAsIdToTest; 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 (unsigned int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1->getGeometricInfo().convert(voxelsAsIndexToTest.at(i), currentId); voxelsAsIdToTest.push_back(currentId); } for (unsigned int i = 0; i < voxelsAsIndexToTest.size(); i++) { //test if the expected interpolation values are computed CHECK_CLOSE(aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i), errorConstant); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIndexToTest.at(i)), aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIdToTest.at(i))); } //test invalid voxels VoxelGridID invalidID(doseAccessor1->getGeometricInfo().getNumberOfVoxels() + 1); VoxelGridIndex3D invalidIndex(doseAccessor1->getGeometricInfo().getNumColumns() + 1, doseAccessor1->getGeometricInfo().getNumRows() + 1, doseAccessor1->getGeometricInfo().getNumSlices() + 1); CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(invalidID), 0.0); CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(invalidIndex), 0.0); CHECK_THROW_EXPLICIT(aRosuMappableDoseAccessorNoPadding->getValueAt(invalidID), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(aRosuMappableDoseAccessorNoPadding->getValueAt(invalidIndex), core::MappingOutsideOfImageException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp index 0506aba..ce53420 100644 --- a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp +++ b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp @@ -1,162 +1,157 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "boost/make_shared.hpp" #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; TransformationInterface::Pointer transformDummy = boost::make_shared(); TransformationInterface::Pointer transformNull; auto interpolationNN = boost::make_shared(); auto interpolationLinear = boost::make_shared(); boost::shared_ptr interpolationNull; auto aSimpleMappableDoseAccessorDefault = boost::make_shared( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy); auto aSimpleMappableDoseAccessorNoPadding = boost::make_shared( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy)); 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->getUID(), doseAccessor2->getUID()); //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 (unsigned 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->getValueAt(currentId), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(currentId), aSimpleMappableDoseAccessorDefault->getValueAt(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->getValueAt(invalidID), 0.0); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(invalidIndex), 0.0); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getValueAt(invalidID), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getValueAt(invalidIndex), core::MappingOutsideOfImageException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/io/dicom/DicomDoseAccessorConverterTest.cpp b/testing/io/dicom/DicomDoseAccessorConverterTest.cpp index 685b816..af37e93 100644 --- a/testing/io/dicom/DicomDoseAccessorConverterTest.cpp +++ b/testing/io/dicom/DicomDoseAccessorConverterTest.cpp @@ -1,123 +1,115 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 a5d1106..e839e86 100644 --- a/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp +++ b/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp @@ -1,108 +1,102 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 6457efa..6cb8a83 100644 --- a/testing/io/dicom/DicomFileReaderHelperTest.cpp +++ b/testing/io/dicom/DicomFileReaderHelperTest.cpp @@ -1,91 +1,87 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 3d7bb6c..dd2263d 100644 --- a/testing/io/dicom/DicomIOTest.cpp +++ b/testing/io/dicom/DicomIOTest.cpp @@ -1,234 +1,227 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 c8d7296..1faac31 100644 --- a/testing/io/dicom/DicomStructureSetGeneratorTest.cpp +++ b/testing/io/dicom/DicomStructureSetGeneratorTest.cpp @@ -1,98 +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. // //------------------------------------------------------------------------ // 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/helax/DicomHelaxDoseAccessorGeneratorTest.cpp b/testing/io/helax/DicomHelaxDoseAccessorGeneratorTest.cpp index 0d400dd..1d60ddc 100644 --- a/testing/io/helax/DicomHelaxDoseAccessorGeneratorTest.cpp +++ b/testing/io/helax/DicomHelaxDoseAccessorGeneratorTest.cpp @@ -1,129 +1,124 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbDicomHelaxIODVecDoseAccessorGenerator.h" -#include "rttbDicomHelaxDoseAccessor.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*!@brief DicomHelaxDoseAccessorGeneratorTest - test the IO for dicom helax data 1) test dicom helax file generator generateDoseAccessor() 2) test dicom helax IOD vector generator generateDoseAccessor() */ int DicomHelaxDoseAccessorGeneratorTest(int argc, char* argv[]) { typedef boost::shared_ptr DRTDoseIODPtr; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: dose directory name // 2: dose1 file name // 3: dose2 file name // 4: dose3 file name std::string RTDOSE_DIRNAME; std::string RTDOSE1_FILENAME; std::string RTDOSE2_FILENAME; std::string RTDOSE3_FILENAME; if (argc > 1) { RTDOSE_DIRNAME = argv[1]; } if (argc > 2) { RTDOSE1_FILENAME = argv[2]; } if (argc > 3) { RTDOSE2_FILENAME = argv[3]; } if (argc > 4) { RTDOSE3_FILENAME = argv[4]; } OFCondition status; DcmFileFormat fileformat; /* test dicom helax file generator generateDoseAccessor() */ CHECK_THROW_EXPLICIT( io::helax::DicomHelaxFileDoseAccessorGenerator("/testAsInvalidDirectoryName/").generateDoseAccessor(), core::InvalidParameterException); CHECK_NO_THROW(io::helax::DicomHelaxFileDoseAccessorGenerator( RTDOSE_DIRNAME.c_str()).generateDoseAccessor()); /* test dicom helax IOD vector generator generateDoseAccessor()*/ DRTDoseIODPtr dose1 = boost::make_shared(); DRTDoseIODPtr dose2 = boost::make_shared(); DRTDoseIODPtr dose3 = boost::make_shared(); std::vector doseVector; //test empty vector CHECK_THROW_EXPLICIT(io::helax::DicomHelaxIODVecDoseAccessorGenerator( doseVector).generateDoseAccessor(), core::InvalidParameterException); doseVector.push_back(dose1); doseVector.push_back(dose2); doseVector.push_back(dose3); //test vector with all empty dose IODs CHECK_THROW_EXPLICIT(io::helax::DicomHelaxIODVecDoseAccessorGenerator( doseVector).generateDoseAccessor(), core::InvalidDoseException); fileformat.loadFile(RTDOSE1_FILENAME.c_str()); dose1->read(*fileformat.getDataset()); fileformat.loadFile(RTDOSE2_FILENAME.c_str()); dose2->read(*fileformat.getDataset()); //test vector with one empty dose IOD CHECK_THROW_EXPLICIT(io::helax::DicomHelaxIODVecDoseAccessorGenerator( doseVector).generateDoseAccessor(), core::InvalidDoseException); fileformat.loadFile(RTDOSE3_FILENAME.c_str()); dose3->read(*fileformat.getDataset()); CHECK_NO_THROW(io::helax::DicomHelaxIODVecDoseAccessorGenerator(doseVector).generateDoseAccessor()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/helax/DicomHelaxIOTest.cpp b/testing/io/helax/DicomHelaxIOTest.cpp index 70714e8..edf4e3b 100644 --- a/testing/io/helax/DicomHelaxIOTest.cpp +++ b/testing/io/helax/DicomHelaxIOTest.cpp @@ -1,121 +1,114 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbDicomHelaxFileDoseAccessorGenerator.h" -#include "rttbDicomHelaxIODVecDoseAccessorGenerator.h" -#include "rttbDicomHelaxDoseAccessor.h" #include "rttbDicomFileStructureSetGenerator.h" namespace rttb { namespace testing { /*!@brief DicomHelaxIOTest - test the IO for dicom helax data 1) test dicom helax dose import if geometric info was set correctly 2) test dicom helax dose import accessing dose data and converting 3) test dicom helax structure import WARNING: The values for comparison need to be adjusted if the input files are changed! */ int DicomHelaxIOTest(int argc, char* argv[]) { typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; typedef core::StructureSet::Pointer StructureSetPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: directory name std::string RT_DIRNAME; if (argc > 1) { RT_DIRNAME = argv[1]; } OFCondition status; DcmFileFormat fileformat; /* read dicom-rt dose */ io::helax::DicomHelaxFileDoseAccessorGenerator doseAccessorGenerator1(RT_DIRNAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //1) test dicom dose import if geometric info was set correctly core::GeometricInfo geoInfo = doseAccessor1->getGeometricInfo(); CHECK_EQUAL(64, geoInfo.getNumRows()); CHECK_EQUAL(54, geoInfo.getNumColumns()); CHECK_EQUAL(52, geoInfo.getNumSlices()); CHECK_EQUAL(OrientationMatrix(), geoInfo.getOrientationMatrix()); 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(doseAccessor1->getValueAt(start), doseAccessor1-> getValueAt(start3D)); inbetween = int(std::floor(doseAccessor1->getGridSize() / 2.0)); doseAccessor1->getGeometricInfo().convert(inbetween, inbetween3D); CHECK_EQUAL(doseAccessor1->getValueAt(inbetween), doseAccessor1-> getValueAt(inbetween3D)); end = doseAccessor1->getGridSize() - 1; doseAccessor1->getGeometricInfo().convert(end, end3D); CHECK_EQUAL(doseAccessor1->getValueAt(end), doseAccessor1-> getValueAt(end3D)); /* structure set */ StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RT_DIRNAME.c_str()).generateStructureSet(); //3) test structure import CHECK_EQUAL(8, rtStructureSet->getNumberOfStructures()); CHECK_EQUAL("Patient outline", (rtStructureSet->getStructure(0))->getLabel()); CHECK_EQUAL("boost", (rtStructureSet->getStructure(1))->getLabel()); CHECK_EQUAL("Chiasma", (rtStructureSet->getStructure(2))->getLabel()); CHECK_EQUAL("Sehnerv li.", (rtStructureSet->getStructure(3))->getLabel()); CHECK_EQUAL("Sehnerv re.", (rtStructureSet->getStructure(4))->getLabel()); CHECK_EQUAL("Auge li.", (rtStructureSet->getStructure(5))->getLabel()); CHECK_EQUAL("Auge re.", (rtStructureSet->getStructure(6))->getLabel()); CHECK_EQUAL("Hirnstamm", (rtStructureSet->getStructure(7))->getLabel()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKBioModelAccessorConverterTest.cpp b/testing/io/itk/ITKBioModelAccessorConverterTest.cpp index 39798cc..be60974 100644 --- a/testing/io/itk/ITKBioModelAccessorConverterTest.cpp +++ b/testing/io/itk/ITKBioModelAccessorConverterTest.cpp @@ -1,105 +1,92 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbDoseIteratorInterface.h" -#include "rttbAccessorInterface.h" #include "rttbDicomFileDoseAccessorGenerator.h" -#include "rttbDicomDoseAccessor.h" #include "rttbLQModelAccessor.h" #include "rttbITKImageAccessor.h" -#include "rttbITKImageFileAccessorGenerator.h" -#include "rttbITKImageAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" -#include "rttbDoseAccessorProcessorBase.h" -#include "rttbDoseAccessorConversionSettingInterface.h" -#include "rttbInvalidDoseException.h" namespace rttb { namespace testing { /*!@brief ITKBioModelAccessorConverterTest - test the conversion rttb BioModel accessor ->itk 1) test with dicom file (DicomDoseAccessorGenerator) */ int ITKBioModelAccessorConverterTest(int argc, char* argv[]) { typedef core::AccessorInterface::Pointer AccessorPointer; typedef core::DoseAccessorInterface::Pointer DoseAccessorPointer; PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } //1) Read dicomFile and test process() and getITKImage() io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor(doseAccessorGenerator.generateDoseAccessor()); AccessorPointer LQWithConstantDose = boost::make_shared(doseAccessor, 0.2, 0.02); io::itk::ITKImageAccessorConverter itkConverter(LQWithConstantDose); CHECK_NO_THROW(itkConverter.process()); CHECK_NO_THROW(itkConverter.getITKImage()); io::itk::ITKImageAccessor::ITKImageType::IndexType itkIndex; itkIndex[0] = itkIndex[1] = itkIndex[2] = 0; VoxelGridIndex3D rttbIndex(0, 0, 0); CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), LQWithConstantDose->getValueAt(rttbIndex)); itkIndex[0] = rttbIndex[0] = doseAccessor->getGeometricInfo().getNumColumns() / 2; itkIndex[1] = rttbIndex[1] = doseAccessor->getGeometricInfo().getNumRows() / 2; itkIndex[2] = rttbIndex[2] = doseAccessor->getGeometricInfo().getNumSlices() / 2; CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), LQWithConstantDose->getValueAt(rttbIndex)); itkIndex[0] = rttbIndex[0] = doseAccessor->getGeometricInfo().getNumColumns() - 1; itkIndex[1] = rttbIndex[1] = doseAccessor->getGeometricInfo().getNumRows() - 1; itkIndex[2] = rttbIndex[2] = doseAccessor->getGeometricInfo().getNumSlices() - 1; CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), LQWithConstantDose->getValueAt(rttbIndex)); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKDoseAccessorConverterTest.cpp b/testing/io/itk/ITKDoseAccessorConverterTest.cpp index f21ee7a..0199f45 100644 --- a/testing/io/itk/ITKDoseAccessorConverterTest.cpp +++ b/testing/io/itk/ITKDoseAccessorConverterTest.cpp @@ -1,127 +1,117 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbITKImageAccessorConverter.h" #include "rttbITKImageFileAccessorGenerator.h" -#include "rttbDoseAccessorProcessorBase.h" -#include "rttbDoseAccessorConversionSettingInterface.h" -#include "rttbInvalidDoseException.h" namespace rttb { namespace testing { /*!@brief ITKDoseAccessorConverterTest - test the conversion rttb dose accessor ->itk 1) test with dicom file (DicomDoseAccessorGenerator) 2) test with mhd file (ITKImageFileDoseAccessorGenerator) */ int ITKDoseAccessorConverterTest(int argc, char* argv[]) { typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: dose1 file name // 2: dose2 file name std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } if (argc > 2) { RTDOSE2_FILENAME = argv[2]; } //1) Read dicomFile and test getITKImage() io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor(doseAccessorGenerator.generateDoseAccessor()); io::itk::ITKImageAccessorConverter itkConverter(doseAccessor); CHECK_NO_THROW(itkConverter.process()); CHECK_NO_THROW(itkConverter.getITKImage()); io::itk::ITKImageAccessorConverter::ITKImageType::IndexType itkIndex; itkIndex[0] = itkIndex[1] = itkIndex[2] = 0; VoxelGridIndex3D rttbIndex(0, 0, 0); CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), doseAccessor->getValueAt(rttbIndex)); itkIndex[0] = rttbIndex[0] = doseAccessor->getGeometricInfo().getNumColumns() / 2; itkIndex[1] = rttbIndex[1] = doseAccessor->getGeometricInfo().getNumRows() / 2; itkIndex[2] = rttbIndex[2] = doseAccessor->getGeometricInfo().getNumSlices() / 2; CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), doseAccessor->getValueAt(rttbIndex)); itkIndex[0] = rttbIndex[0] = doseAccessor->getGeometricInfo().getNumColumns() - 1; itkIndex[1] = rttbIndex[1] = doseAccessor->getGeometricInfo().getNumRows() - 1; itkIndex[2] = rttbIndex[2] = doseAccessor->getGeometricInfo().getNumSlices() - 1; CHECK_EQUAL(itkConverter.getITKImage()->GetPixel(itkIndex), doseAccessor->getValueAt(rttbIndex)); //2) Read mhdFile and test getITKImage() with Litmus TestImageIO io::itk::ITKImageFileAccessorGenerator doseAccessorGenerator2(RTDOSE2_FILENAME.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); io::itk::ITKImageAccessorConverter itkConverter2(doseAccessor2); CHECK_NO_THROW(itkConverter2.process()); CHECK_NO_THROW(itkConverter2.getITKImage()); io::itk::ITKImageAccessorConverter::ITKImageType::Pointer expectedImage = lit::TestImageIO::readImage( RTDOSE2_FILENAME); ::lit::ImageTester tester; tester.setExpectedImage(expectedImage); tester.setActualImage(itkConverter2.getITKImage()); CHECK_TESTER(tester); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp b/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp index d19514c..9c38a10 100644 --- a/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp +++ b/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp @@ -1,100 +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. // //------------------------------------------------------------------------ // 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 "itkExceptionObject.h" -#include "rttbBaseType.h" -#include "rttbITKImageAccessorConverter.h" #include "rttbITKImageAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.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 with short image type // 2: mhd/raw file name with double image type std::string ITKSHORTFILE_FILENAME, ITKDOUBLEFILE_FILENAME, ITK2DVECTORFILE_FILENAME, ITK2DFILE_FILENAME; if (argc > 4) { ITKSHORTFILE_FILENAME = argv[1]; ITKDOUBLEFILE_FILENAME = argv[2]; ITK2DVECTORFILE_FILENAME = argv[3]; ITK2DFILE_FILENAME = argv[4]; } /* test ITKFileDoseAccessorGenerator generateDoseAccessor()*/ CHECK_THROW_EXPLICIT(io::itk::ITKImageFileAccessorGenerator("test.test").generateDoseAccessor(), core::InvalidDoseException); CHECK_NO_THROW(io::itk::ITKImageFileAccessorGenerator( ITKSHORTFILE_FILENAME.c_str()).generateDoseAccessor()); CHECK_NO_THROW(io::itk::ITKImageFileAccessorGenerator( ITKDOUBLEFILE_FILENAME.c_str()).generateDoseAccessor()); CHECK_THROW_EXPLICIT(io::itk::ITKImageFileAccessorGenerator( ITK2DFILE_FILENAME.c_str()).generateDoseAccessor(), core::InvalidParameterException); CHECK_THROW(io::itk::ITKImageFileAccessorGenerator( ITK2DVECTORFILE_FILENAME.c_str()).generateDoseAccessor()); /* test ITKDoseAccessorGenerator generateDoseAccessor()*/ typedef itk::Image< DoseTypeGy, 3 > DoseImageType; typedef itk::ImageFileReader ReaderType; DoseImageType::Pointer invalidDose = DoseImageType::New(); ReaderType::Pointer reader = ReaderType::New(); CHECK_THROW_EXPLICIT(io::itk::ITKImageAccessorGenerator( invalidDose.GetPointer()).generateDoseAccessor(), core::InvalidDoseException); reader->SetFileName(ITKSHORTFILE_FILENAME); //important to update the reader (won't work without) reader->Update(); CHECK_NO_THROW(io::itk::ITKImageAccessorGenerator(reader->GetOutput()).generateDoseAccessor()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKIOTest.cpp b/testing/io/itk/ITKIOTest.cpp index 3d179f1..3f509d8 100644 --- a/testing/io/itk/ITKIOTest.cpp +++ b/testing/io/itk/ITKIOTest.cpp @@ -1,210 +1,205 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbGeometricInfo.h" #include "rttbDoseIteratorInterface.h" -#include "rttbITKImageAccessorConverter.h" #include "rttbITKImageAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbITKImageFileMaskAccessorGenerator.h" #include "rttbITKImageAccessor.h" -#include "rttbITKImageMaskAccessor.h" #include "rttbInvalidDoseException.h" #include "itkImageFileReader.h" namespace rttb { namespace testing { /*!@brief ITKIOTest - test the IO for ITK data 1) test ITK dose import if geometric info was set correctly 2) test ITKImageFileDoseAccessorGenerator accessing dose data and converting (*.mhd file) 3) test ITKImageDoseAccessorGenerator accessing dose data and converting (*.mhd file) WARNING: The values for comparison need to be adjusted if the input files are changed! */ int ITKIOTest(int argc, char* argv[]) { typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; typedef core::MaskAccessorInterface::Pointer MaskAccessorPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: mhd file name // 2: mask file name std::string RTDOSE_FILENAME, VOXELIZEDMASK_FILENAME; if (argc > 2) { RTDOSE_FILENAME = argv[1]; VOXELIZEDMASK_FILENAME = argv[2]; } /* read dose in *.mhd file */ io::itk::ITKImageFileAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //1) test ITK dose import if geometric info was set correctly core::GeometricInfo geoInfo = doseAccessor1->getGeometricInfo(); CHECK_EQUAL(25, geoInfo.getNumRows()); CHECK_EQUAL(25, geoInfo.getNumColumns()); CHECK_EQUAL(15, geoInfo.getNumSlices()); //orientation matrix equals identity matrix CHECK_EQUAL(OrientationMatrix(), geoInfo.getOrientationMatrix()); const VoxelGridID start = 0; const VoxelGridIndex3D start3D(0); VoxelGridID end, inbetween, inbetween2, outside; VoxelGridIndex3D end3D, inbetween3D, inbetween23D, outside3D; //2) test ITK dose import accessing dose data and converting (*.mhd file) CHECK(doseAccessor1->getGeometricInfo().validID(start)); CHECK(doseAccessor1->getGeometricInfo().validIndex(start3D)); CHECK(!(doseAccessor1->getGeometricInfo().validID(doseAccessor1->getGridSize()))); CHECK(!(doseAccessor1->getGeometricInfo().validIndex(VoxelGridIndex3D( doseAccessor1->getGridSize())))); CHECK_EQUAL(0, doseAccessor1->getValueAt(start)); CHECK_EQUAL(doseAccessor1->getValueAt(start), doseAccessor1-> getValueAt(start3D)); CHECK_NO_THROW(doseAccessor1->getUID()); inbetween = 4039; doseAccessor1->getGeometricInfo().convert(inbetween, inbetween3D); CHECK(doseAccessor1->getGeometricInfo().validID(inbetween)); CHECK(doseAccessor1->getGeometricInfo().validIndex(inbetween3D)); CHECK_EQUAL(162.0, doseAccessor1->getValueAt(inbetween)); CHECK_EQUAL(doseAccessor1->getValueAt(inbetween), doseAccessor1-> getValueAt(inbetween3D)); inbetween2 = 6086; doseAccessor1->getGeometricInfo().convert(inbetween2, inbetween23D); CHECK(doseAccessor1->getGeometricInfo().validID(inbetween2)); CHECK(doseAccessor1->getGeometricInfo().validIndex(inbetween23D)); CHECK_EQUAL(7.0, doseAccessor1->getValueAt(inbetween2)); CHECK_EQUAL(doseAccessor1->getValueAt(inbetween2), doseAccessor1-> getValueAt(inbetween23D)); end = doseAccessor1->getGridSize() - 1; outside = end + 1; doseAccessor1->getGeometricInfo().convert(end, end3D); outside3D = VoxelGridIndex3D(end3D.x() + 2, end3D.y(), end3D.z()); CHECK(doseAccessor1->getGeometricInfo().validID(end)); CHECK(doseAccessor1->getGeometricInfo().validIndex(end3D)); CHECK_EQUAL(0, doseAccessor1->getValueAt(end)); CHECK_EQUAL(doseAccessor1->getValueAt(end), doseAccessor1-> getValueAt(end3D)); CHECK_EQUAL(-1, doseAccessor1->getValueAt(outside)); CHECK_EQUAL(-1, doseAccessor1->getValueAt(outside3D)); typedef itk::Image< DoseTypeGy, 3 > DoseImageType; typedef itk::ImageFileReader ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(RTDOSE_FILENAME); //important to update the reader (won't work without) reader->Update(); io::itk::ITKImageAccessorGenerator doseAccessorGenerator2(reader->GetOutput()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); //3) test ITK dose import accessing dose data and converting (ITKImageDoseAccessor) CHECK(doseAccessor2->getGeometricInfo().validID(start)); CHECK(doseAccessor2->getGeometricInfo().validIndex(start3D)); CHECK(!(doseAccessor2->getGeometricInfo().validID(doseAccessor2->getGridSize()))); CHECK(!(doseAccessor2->getGeometricInfo().validIndex(VoxelGridIndex3D( doseAccessor2->getGridSize())))); CHECK_EQUAL(0, doseAccessor2->getValueAt(start)); CHECK_EQUAL(doseAccessor2->getValueAt(start), doseAccessor2->getValueAt(start3D)); CHECK(doseAccessor2->getGeometricInfo().validID(inbetween)); CHECK(doseAccessor2->getGeometricInfo().validIndex(inbetween3D)); CHECK_EQUAL(162.0, doseAccessor2->getValueAt(inbetween)); CHECK_EQUAL(doseAccessor2->getValueAt(inbetween), doseAccessor2->getValueAt(inbetween3D)); CHECK(doseAccessor2->getGeometricInfo().validID(inbetween2)); CHECK(doseAccessor2->getGeometricInfo().validIndex(inbetween23D)); CHECK_EQUAL(7.0, doseAccessor2->getValueAt(inbetween2)); CHECK_EQUAL(doseAccessor2->getValueAt(inbetween2), doseAccessor2->getValueAt(inbetween23D)); end = doseAccessor2->getGridSize() - 1; doseAccessor2->getGeometricInfo().convert(end, end3D); CHECK(doseAccessor2->getGeometricInfo().validID(end)); CHECK(doseAccessor2->getGeometricInfo().validIndex(end3D)); CHECK_EQUAL(0, doseAccessor2->getValueAt(end)); CHECK_EQUAL(doseAccessor2->getValueAt(end), doseAccessor2-> getValueAt(end3D)); /* test ITKImageAccessor*/ typedef itk::Image< DoseTypeGy, 3 > DoseImageType; DoseImageType::Pointer invalidDose = DoseImageType::New(); CHECK_THROW_EXPLICIT(io::itk::ITKImageAccessor(invalidDose.GetPointer()), core::InvalidDoseException); /* test ITKImageMaskAccessor*/ CHECK_THROW_EXPLICIT(io::itk::ITKImageMaskAccessor(invalidDose.GetPointer()), core::InvalidDoseException); io::itk::ITKImageFileMaskAccessorGenerator maskAccessorGenerator(VOXELIZEDMASK_FILENAME.c_str()); MaskAccessorPointer maskAccessor(maskAccessorGenerator.generateMaskAccessor()); auto imageSize = maskAccessor->getGeometricInfo().getImageSize(); end = imageSize.x()*imageSize.y()*imageSize.z() - 1; outside = end + 1; maskAccessor->getGeometricInfo().convert(end, end3D); outside3D = VoxelGridIndex3D(end3D.x() + 2, end3D.y(), end3D.z()); inbetween3D = VoxelGridIndex3D(139, 61, 57); maskAccessor->getGeometricInfo().convert(inbetween3D, inbetween); core::MaskVoxel aVoxel(0); CHECK_EQUAL(maskAccessor->getMaskAt(start, aVoxel), true); CHECK_EQUAL(aVoxel.getRelevantVolumeFraction(), 0.0); CHECK_EQUAL(maskAccessor->getMaskAt(end, aVoxel), true); CHECK_EQUAL(aVoxel.getRelevantVolumeFraction(), 0.0); CHECK_EQUAL(maskAccessor->getMaskAt(end3D, aVoxel), true); CHECK_EQUAL(aVoxel.getRelevantVolumeFraction(), 0.0); CHECK_EQUAL(maskAccessor->getMaskAt(outside, aVoxel), false); CHECK_EQUAL(maskAccessor->getMaskAt(outside3D, aVoxel), false); CHECK_EQUAL(maskAccessor->getMaskAt(inbetween, aVoxel), true); CHECK_EQUAL(aVoxel.getRelevantVolumeFraction(), 1.0); CHECK_EQUAL(maskAccessor->getMaskAt(inbetween3D, aVoxel), true); CHECK_EQUAL(aVoxel.getRelevantVolumeFraction(), 1.0); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKMaskAccessorConverterTest.cpp b/testing/io/itk/ITKMaskAccessorConverterTest.cpp index 47350d4..b8c4da3 100644 --- a/testing/io/itk/ITKMaskAccessorConverterTest.cpp +++ b/testing/io/itk/ITKMaskAccessorConverterTest.cpp @@ -1,170 +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. // //------------------------------------------------------------------------ // 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 "rttbBoostMaskAccessor.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::StructureSet::Pointer StructureSetPointer; typedef core::MaskAccessorInterface::Pointer 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(9), 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; ITKImageTypePointer convertedImagePtr = maskAccessorConverter2.getITKImage(); 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]); CHECK_EQUAL(convertedImagePtr->GetLargestPossibleRegion().GetSize()[0], expectedImage->GetLargestPossibleRegion().GetSize()[0]); CHECK_EQUAL(convertedImagePtr->GetLargestPossibleRegion().GetSize()[1], expectedImage->GetLargestPossibleRegion().GetSize()[1]); CHECK_EQUAL(convertedImagePtr->GetLargestPossibleRegion().GetSize()[2], expectedImage->GetLargestPossibleRegion().GetSize()[2]); unsigned int sizeX = convertedImagePtr->GetLargestPossibleRegion().GetSize()[0]; unsigned int sizeY = convertedImagePtr->GetLargestPossibleRegion().GetSize()[1]; unsigned int sizeZ = convertedImagePtr->GetLargestPossibleRegion().GetSize()[2]; io::itk::ITKImageMaskAccessor::ITKMaskImageType::IndexType index; for (unsigned int i = 0; i < 20 && i < sizeX && i < sizeY && i < sizeZ; i++) { index[0] = i; index[1] = i; index[2] = 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; 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 ac6cee6..3d5d3fd 100644 --- a/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp +++ b/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp @@ -1,94 +1,90 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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::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()); CHECK_EQUAL(maskAcc->isGridHomogeneous(), true); CHECK_NO_THROW(maskAcc->getMaskUID()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/models/ModelsIOTest.cpp b/testing/io/models/ModelsIOTest.cpp index 712d68c..085f740 100644 --- a/testing/io/models/ModelsIOTest.cpp +++ b/testing/io/models/ModelsIOTest.cpp @@ -1,132 +1,130 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // (c) Copyright 2007, DKFZ, Heidelberg, Germany // ALL RIGHTS RESERVED // // THIS FILE CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION OF DKFZ. // ANY DUPLICATION, MODIFICATION, DISTRIBUTION, OR // DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY PROHIBITED // WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF DKFZ. // //------------------------------------------------------------------------ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include "litCheckMacros.h" -#include "rttbBioModel.h" #include "rttbTCPLQModel.h" #include "rttbNTCPLKBModel.h" #include -#include #include "boost/filesystem.hpp" #include "rttbModelXMLWriter.h" namespace rttb { namespace testing { static std::string readFile(const std::string& filename); int ModelsIOTest(int argc, char* argv[]) { std::string expectedxmlfilenametcpleq; std::string expectedxmlfilenamentcplk; if (argc > 2) { expectedxmlfilenametcpleq = argv[1]; expectedxmlfilenamentcplk = argv[2]; } typedef core::DVH::DataDifferentialType DataDifferentialType; PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; DataDifferentialType aDataDifferential; DoseCalcType value = 0; DVHVoxelNumber numberOfVoxels = 0; // creat default values for (int i = 0; i < 98; i++) { value = 0; numberOfVoxels += value; aDataDifferential.push_back(value); } aDataDifferential.push_back(10); aDataDifferential.push_back(20); const IDType structureID = "myStructure"; const IDType doseID = "myDose"; const IDType voxelizationID = "myVoxelization"; core::DVH::Pointer dvhPtr = boost::make_shared(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); //test TCP LQ Model models::BioModelParamType alpha = 0.35; models::BioModelParamType beta = 0.023333333333333; models::BioModelParamType roh = 10000000; int numFractions = 8; boost::shared_ptr tcplq = boost::make_shared (dvhPtr, roh, numFractions, alpha / beta, alpha, 0.08); std::string filename = "BioModeltcpleqIOTest.xml"; rttb::io::models::ModelXMLWriter writer = rttb::io::models::ModelXMLWriter(filename, tcplq, false); CHECK_NO_THROW(writer.writeModel()); CHECK_EQUAL(boost::filesystem::exists(filename), true); std::string defaultAsIs = readFile(filename); std::string defaultExpected = readFile(expectedxmlfilenametcpleq); //Does not work due to double imprecisions. As long as we don't have a ModelXMLReader, a check does not makes sense. See T21832 //CHECK_EQUAL(defaultAsIs, defaultExpected); CHECK_EQUAL(std::remove(filename.c_str()), 0); //test NTCPLKBModel models::BioModelParamType aVal = 10; models::BioModelParamType mVal = 0.16; models::BioModelParamType d50Val = 35; boost::shared_ptr ntcplk = boost::make_shared(dvhPtr, d50Val, mVal, aVal); filename = "BioModelntcplkIOTest.xml"; rttb::io::models::ModelXMLWriter writer2 = rttb::io::models::ModelXMLWriter(filename, ntcplk); CHECK_NO_THROW(writer2.writeModel()); CHECK_EQUAL(boost::filesystem::exists(filename), true); defaultAsIs = readFile(filename); defaultExpected = readFile(expectedxmlfilenamentcplk); //Does not work due to double imprecisions. As long as we don't have a ModelXMLReader, a check does not makes sense. See T21832 //CHECK_EQUAL(defaultAsIs, defaultExpected); CHECK_EQUAL(std::remove(filename.c_str()), 0); std::string dvhFilename = "dvhfor" + ntcplk->getModelType() + ".xml"; CHECK_EQUAL(std::remove(dvhFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } std::string readFile(const std::string& filename) { std::ifstream fileStream(filename.c_str()); std::string content((std::istreambuf_iterator(fileStream)), (std::istreambuf_iterator())); return content; } } } diff --git a/testing/io/other/DVHXMLIOTest.cpp b/testing/io/other/DVHXMLIOTest.cpp index eb7647c..8fc80e2 100644 --- a/testing/io/other/DVHXMLIOTest.cpp +++ b/testing/io/other/DVHXMLIOTest.cpp @@ -1,101 +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. // //------------------------------------------------------------------------ // 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 "rttbDVH.h" -#include "rttbDVHSet.h" #include "rttbDVHXMLFileReader.h" #include "rttbDVHXMLFileWriter.h" -#include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "../../core/DummyDVHGenerator.h" -#include "CompareDVH.h" - namespace rttb { namespace testing { /*! @brief DVHXMLIOTest - test the IO for DVH xml data 1) test writing dvh to xml file 2) test reading DVH from xml file */ int DVHXMLIOTest(int argc, char* argv[]) { typedef core::DVH::Pointer DVHPointer; PREPARE_DEFAULT_TEST_REPORTING; /* generate dummy DVH */ const IDType structureIDPrefix = "myStructure"; const IDType doseID = "myDose"; DummyDVHGenerator dvhGenerator; DVHPointer spMyDVH = boost::make_shared(dvhGenerator.generateDVH(structureIDPrefix, doseID)); // 1) test writing DVH to xml file DVHType typeCum = {DVHType::Cumulative}; DVHType typeDiff = {DVHType::Differential}; FileNameString fN1 = "test.xml"; CHECK_NO_THROW(io::other::DVHXMLFileWriter(fN1, typeDiff)); CHECK_NO_THROW(io::other::DVHXMLFileWriter(fN1, typeCum)); io::other::DVHXMLFileWriter dvhWriter(fN1, typeCum); CHECK_EQUAL(fN1, dvhWriter.getFileName()); FileNameString fN2 = "otherFile.xml"; CHECK_NO_THROW(dvhWriter.setFileName(fN2)); CHECK_EQUAL(fN2, dvhWriter.getFileName()); CHECK_EQUAL(DVHType::Cumulative, dvhWriter.getDVHType().Type); CHECK_NO_THROW(dvhWriter.setDVHType(typeDiff)); CHECK_EQUAL(DVHType::Differential, dvhWriter.getDVHType().Type); DVHPointer emptyDvh; CHECK_THROW_EXPLICIT(dvhWriter.writeDVH(emptyDvh), core::NullPointerException); //CHECK_THROW_EXPLICIT(dvhWriter.writeDVH(spMyDVH), core::InvalidParameterException); CHECK_NO_THROW(dvhWriter.setDVHType(typeDiff)); CHECK_NO_THROW(dvhWriter.writeDVH(spMyDVH)); // 2) test reading DVH from xml file io::other::DVHXMLFileReader dvhReader(fN2); DVHPointer importedDVH = dvhReader.generateDVH(); CHECK_EQUAL(*importedDVH, *spMyDVH); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/other/DoseStatisticsIOTest.cpp b/testing/io/other/DoseStatisticsIOTest.cpp index 16ab4c2..bcdcc02 100644 --- a/testing/io/other/DoseStatisticsIOTest.cpp +++ b/testing/io/other/DoseStatisticsIOTest.cpp @@ -1,131 +1,125 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 #include -#include "litCheckMacros.h" - -#include "rttbDoseStatistics.h" #include "rttbDoseStatisticsCalculator.h" #include "rttbDoseStatisticsXMLWriter.h" #include "rttbDoseStatisticsXMLReader.h" #include "rttbGenericDoseIterator.h" -#include "rttbDoseIteratorInterface.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "../../core/DummyDoseAccessor.h" #include "CompareDoseStatistic.h" namespace rttb { namespace testing { /*! @brief DoseStatisticsIOTest - test the DoseStatisticsIO for dose statistics 1) test writing statistics to xml file 2) test reading statistics from XML file and compare DoseStatistics 3) test writing statistics to string */ int DoseStatisticsIOTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::Pointer DoseIteratorPointer; PREPARE_DEFAULT_TEST_REPORTING; /* generate dummy dose */ boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); auto myDoseStatsSimple = myDoseStatsCalculator.calculateDoseStatistics(); auto myDoseStatsComplex = myDoseStatsCalculator.calculateDoseStatistics(true); auto doseStatisticsXMLWriter = io::other::DoseStatisticsXMLWriter(); //1) test writing statistics to xml file CHECK_THROW_EXPLICIT(doseStatisticsXMLWriter.writeDoseStatistics(nullptr, "aFilename.txt"), core::NullPointerException); FileNameString filenameSimple = "testStatisticsSimple.xml"; CHECK_NO_THROW(doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsSimple, filenameSimple)); CHECK(boost::filesystem::exists(filenameSimple)); FileNameString filenameComplex = "testStatisticsComplex.xml"; CHECK_NO_THROW(doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsComplex, filenameComplex)); CHECK(boost::filesystem::exists(filenameComplex)); //2) test reading statistics from XML file and compare DoseStatistics io::other::DoseStatisticsXMLReader readerSimple= io::other::DoseStatisticsXMLReader(filenameSimple); boost::shared_ptr rereadSimplyDose; CHECK_NO_THROW(rereadSimplyDose = readerSimple.generateDoseStatistic()); CHECK(checkEqualDoseStatistic(myDoseStatsSimple, rereadSimplyDose)); io::other::DoseStatisticsXMLReader readerComplex = io::other::DoseStatisticsXMLReader(filenameComplex); boost::shared_ptr rereadComplexDose; CHECK_NO_THROW(rereadComplexDose = readerComplex.generateDoseStatistic()); CHECK(checkEqualDoseStatistic(myDoseStatsComplex, rereadComplexDose)); io::other::DoseStatisticsXMLReader readerInvalidFilename = io::other::DoseStatisticsXMLReader("invalidFilename.xml"); CHECK_THROW_EXPLICIT(readerInvalidFilename.generateDoseStatistic(), core::InvalidParameterException); //delete files again CHECK_EQUAL(std::remove(filenameSimple.c_str()), 0); CHECK_EQUAL(std::remove(filenameComplex.c_str()),0); //3) test writing statistics to string boost::property_tree::ptree ptSimple = doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsSimple); XMLString strSimple = doseStatisticsXMLWriter.writerDoseStatisticsToString(myDoseStatsSimple); CHECK_THROW_EXPLICIT(doseStatisticsXMLWriter.writerDoseStatisticsToString(nullptr), core::NullPointerException); boost::property_tree::ptree ptComplex = doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsComplex); XMLString strComplex = doseStatisticsXMLWriter.writerDoseStatisticsToString(myDoseStatsComplex); std::stringstream sstrSimple; boost::property_tree::xml_parser::write_xml(sstrSimple, ptSimple, boost::property_tree::xml_writer_make_settings('\t', 1)); CHECK_EQUAL(strSimple, sstrSimple.str()); std::stringstream sstrComplex; boost::property_tree::xml_parser::write_xml(sstrComplex, ptComplex, boost::property_tree::xml_writer_make_settings('\t', 1)); CHECK_EQUAL(strComplex, sstrComplex.str()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/masks/BoostMaskTest.cpp b/testing/masks/BoostMaskTest.cpp index a88f2f4..dcfde1f 100644 --- a/testing/masks/BoostMaskTest.cpp +++ b/testing/masks/BoostMaskTest.cpp @@ -1,247 +1,236 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" - #include "../core/DummyStructure.h" #include "../core/DummyDoseAccessor.h" -#include "rttbDicomDoseAccessor.h" -#include "rttbDicomFileDoseAccessorGenerator.h" -#include "rttbDicomFileStructureSetGenerator.h" -#include "rttbDicomFileStructureSetGenerator.h" -#include "rttbGenericDoseIterator.h" -#include "rttbDVHCalculator.h" -#include "rttbGenericMaskedDoseIterator.h" #include "rttbBoostMask.h" #include "rttbBoostMaskAccessor.h" -#include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief BoostMaskRedesignTest. 1) test constructors 2) test getRelevantVoxelVector 3) test getMaskAt */ int BoostMaskTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef core::Structure::Pointer StructTypePointer; // generate test dose. geometric info: patient position (-25, -2, 35), center of the 1st.voxel boost::shared_ptr spTestDoseAccessor = boost::make_shared(); boost::shared_ptr geometricPtr = boost::make_shared (spTestDoseAccessor->getGeometricInfo()); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); //generate test structure. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 41.25); (-12.5, 0.5, 41.25); (-12.5, 10.5, 41.25); (-20, 10.5, 41.25); core::Structure myTestStruct = myStructGenerator.CreateRectangularStructureCentered(2,3); StructTypePointer spMyStruct = boost::make_shared(myTestStruct); //generate test structure 2. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 40); (-12.5, 0.5, 40); (-12.5, 10.5, 40); (-20, 10.5, 40); core::Structure myTestStruct2 = myStructGenerator.CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(2); StructTypePointer spMyStruct2 = boost::make_shared(myTestStruct2); //generate test structure. contours are //(-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 41.25); (-12.5, 0.5, 41.25); (-12.5, 10.5, 41.25); (-20, 10.5, 41.25); //(-20, 0.5, 48.75); (-12.5, 0.5, 48.75); (-12.5, 10.5, 48.75); (-20, 10.5, 48.75); //(-20, 0.5, 51.25); (-12.5, 0.5, 51.25); (-12.5, 10.5, 51.25); (-20, 10.5, 51.25); //to test calcVoxelizationThickness bug core::Structure myTestStruct3 = myStructGenerator.CreateRectangularStructureCentered(2, 3, 6, 7); StructTypePointer spMyStruct3 = boost::make_shared(myTestStruct3); //1) test BoostMask & BoostMaskAccessor constructor CHECK_NO_THROW(rttb::masks::boost::BoostMask(geometricPtr, spMyStruct)); rttb::masks::boost::BoostMask boostMask = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct); CHECK_NO_THROW(rttb::masks::boost::BoostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true)); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true); //2) test getRelevantVoxelVector CHECK_NO_THROW(boostMask.getRelevantVoxelVector()); CHECK_NO_THROW(boostMaskAccessor.getRelevantVoxelVector()); //3) test getMaskAt const VoxelGridIndex3D inMask1(2, 1, 2); //corner between two contours slice -> volumeFraction = 0.25 const VoxelGridIndex3D inMask2(3, 4, 2); //inside between two contours slice ->volumeFraction = 1 const VoxelGridIndex3D inMask3(4, 5, 2); //side between two contours slice -> volumeFraction = 0.5 const VoxelGridIndex3D inMask4(2, 1, 1); //corner on the first contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask5(2, 1, 3); //corner on the last contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask6(3, 4, 1); //inside on the first contour slice ->volumeFraction = 1 /2 = 0.5 const VoxelGridIndex3D outMask1(7, 5, 4); const VoxelGridIndex3D outMask2(2, 1, 0); const VoxelGridIndex3D outMask3(2, 1, 4); VoxelGridID testId; double errorConstantBoostMask = 1e-7; core::MaskVoxel tmpMV1(0), tmpMV2(0); CHECK(boostMaskAccessor.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(1, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask5, tmpMV1)); CHECK(geometricPtr->convert(inMask5, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); rttb::masks::boost::BoostMask boostMask2 = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct2); CHECK_NO_THROW(boostMask2.getRelevantVoxelVector()); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor2(spMyStruct2, spTestDoseAccessor->getGeometricInfo(), true); CHECK_NO_THROW(boostMaskAccessor2.getRelevantVoxelVector()); CHECK(boostMaskAccessor2.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner, the first contour weight 0.25, the second contour weights 0.5 -> volumeFraction = 0.25*0.25 + 1.25*0.5 = 0.1875 CHECK_CLOSE(0.1875, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside, the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 1*0.25 + 1*0.5 = 0.75 CHECK_EQUAL(0.75, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //side the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 0.5*0.25 + 0.5*0.5 = 0.75 CHECK_CLOSE(0.375, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner on the first contour slice, weight 0.25 -> volumeFraction = 0.25*0.25 = 0.0625 CHECK_CLOSE(0.0625, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside on the first contour slice, weight 0.25 ->volumeFraction = 1 * 0.25 = 0.25 CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor2.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask //3) test calcVoxelizationThickness bug rttb::masks::boost::BoostMask boostMask3 = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct3); CHECK_NO_THROW(boostMask3.getRelevantVoxelVector()); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor3(spMyStruct3, spTestDoseAccessor->getGeometricInfo(), true); CHECK_NO_THROW(boostMaskAccessor3.getRelevantVoxelVector()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/models/BioModelScatterPlotTest.cpp b/testing/models/BioModelScatterPlotTest.cpp index 2b4c4fd..73f6e99 100644 --- a/testing/models/BioModelScatterPlotTest.cpp +++ b/testing/models/BioModelScatterPlotTest.cpp @@ -1,233 +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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbBaseTypeModels.h" -#include "rttbBioModel.h" #include "rttbBioModelScatterPlots.h" #include "../core/DummyDVHGenerator.h" #include "DummyModel.h" -#include "rttbIntegration.h" - -#include -#include -#include namespace rttb { namespace testing { typedef models::ScatterPlotType ScatterPlotType; /*! @brief BioModelScatterPlotTest. Test the scatterplot methods. 1) test if parameters are set correctly 2) test if scatterData contain each model value exactly once */ int BioModelScatterPlotTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DummyDVHGenerator dummyDVH; const IDType structureID = "myStructure"; const IDType doseID = "myDose"; core::DVH::Pointer dvhPtr = boost::make_shared(dummyDVH.generateDVH(structureID, doseID, 0, 2000)); //test Dummy Model models::BioModelParamType param1 = 0.35; models::BioModelParamType param2 = 0.023333333333333; models::BioModelParamType param3 = 10000000; //model values will be dose/normalisationDose DoseTypeGy normalisationDose = 10; rttb::models::DummyModel model(dvhPtr); model.resetCounters(); //default number of points is 100 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 0, param1, 0.5, normalisationDose)); model.resetCounters(); ScatterPlotType scatter = models::getScatterPlotVary1Parameter(model, 0, param1, 0.5, normalisationDose); //only 1st parameter should gave been changed CHECK_EQUAL(100, model.getSetParam1Count()); CHECK_EQUAL(0, model.getSetParam2Count()); CHECK_EQUAL(0, model.getSetParam3Count()); CHECK_EQUAL(100, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose ScatterPlotType::iterator iter; for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //number of points is 50 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 1, param2, 0.25, normalisationDose, 50)); model.resetCounters(); scatter = models::getScatterPlotVary1Parameter(model, 1, param2, 0.25, normalisationDose, 50); //only 1st parameter should gave been changed CHECK_EQUAL(0, model.getSetParam1Count()); CHECK_EQUAL(50, model.getSetParam2Count()); CHECK_EQUAL(0, model.getSetParam3Count()); CHECK_EQUAL(50, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //number of points is 150 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 2, param3, 0.75, normalisationDose, 150)); model.resetCounters(); scatter = models::getScatterPlotVary1Parameter(model, 2, param3, 0.75, normalisationDose, 150); //only 1st parameter should gave been changed CHECK_EQUAL(0, model.getSetParam1Count()); CHECK_EQUAL(0, model.getSetParam2Count()); CHECK_EQUAL(150, model.getSetParam3Count()); CHECK_EQUAL(150, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); std::vector paramIDVec; models::BioModel::ParamVectorType meanVec; models::BioModel::ParamVectorType varianceVec; paramIDVec.push_back(0); meanVec.push_back(1); varianceVec.push_back(0.6); paramIDVec.push_back(1); meanVec.push_back(10); varianceVec.push_back(0.5); paramIDVec.push_back(2); meanVec.push_back(100); varianceVec.push_back(0.4); //number of points is 50 CHECK_NO_THROW(models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 50)); model.resetCounters(); scatter = models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 50); //only 1st parameter should gave been changed CHECK_EQUAL(50, model.getSetParam1Count()); CHECK_EQUAL(50, model.getSetParam2Count()); CHECK_EQUAL(50, model.getSetParam3Count()); CHECK_EQUAL(50, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //test 2000 points CHECK_NO_THROW(models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 10000)); //test iterativeIntegration /*std::string bedFileName="d:/Temp/bed.txt"; std::ifstream dvh_ifstr(bedFileName,std::ios::in); std::vector volumeV2; std::vector bedV2; //std::cout << "iterative integration"<< std::endl; if ( !dvh_ifstr.is_open() ) { std::cerr<< "DVH file name invalid: could not open the dvh file!"<> volume; volumeV2.push_back(volume); //std::cout << "("<< volume << ","; std::string lineSub2 = line.substr(found2+1,found3-found2-1); //std::cout << lineSub2 << std::endl; std::stringstream ss2(lineSub2); double bed; ss2 >> bed; bedV2.push_back(bed); //std::cout << bed << ");"; } } } struct rttb::models::TcpParams params={0.302101,0.08,10000000,volumeV2,bedV2}; double result = rttb::models::integrateTCP(0, params);*/ RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/models/BioModelTest.cpp b/testing/models/BioModelTest.cpp index 6f4e9be..af77474 100644 --- a/testing/models/BioModelTest.cpp +++ b/testing/models/BioModelTest.cpp @@ -1,297 +1,291 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbBaseType.h" -#include "rttbBaseTypeModels.h" -#include "rttbBioModel.h" -#include "rttbDVH.h" #include "rttbTCPLQModel.h" #include "rttbNTCPLKBModel.h" #include "rttbNTCPRSModel.h" -#include "rttbBaseTypeModels.h" #include "rttbBioModelCurve.h" #include "rttbInvalidParameterException.h" #include "rttbBioModelScatterPlots.h" namespace rttb { namespace testing { typedef core::DVH::DataDifferentialType DataDifferentialType; /*! @brief RTBioModelTest. TCP calculated using a DVH PTV and LQ Model. NTCP tested using 3 Normal Tissue DVHs and LKB/RS Model. TCPLQ: 1) test constructors (values as expected?) 2) test init (calcTCPxxx) 3) test set/get NTCP (LKB): 1) test constructors (values as expected?) 2) test init (calcxxx) 3) test set/get NTCP (RS): 1) test constructors (values as expected?) 2) test init (calcxxx) 3) test set/get */ int BioModelTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; DataDifferentialType aDataDifferential; DoseCalcType value = 0; DVHVoxelNumber numberOfVoxels = 0; // creat default values for (int i = 0; i < 98; i++) { value = 0; numberOfVoxels += value; aDataDifferential.push_back(value); } aDataDifferential.push_back(10); aDataDifferential.push_back(20); const IDType structureID = "myStructure"; const IDType doseID = "myDose"; const IDType voxelizationID = "myVoxelization"; core::DVH::Pointer dvhPtr = boost::make_shared(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); //test TCP LQ Model models::BioModelParamType alpha = 0.35; models::BioModelParamType beta = 0.023333333333333; models::BioModelParamType roh = 10000000; int numFractions = 8; DoseTypeGy normalizationDose = 50; //1) test constructors (values as expected?) rttb::models::TCPLQModel tcplq = rttb::models::TCPLQModel(); CHECK_EQUAL(0, tcplq.getAlphaMean()); CHECK_EQUAL(0, tcplq.getAlphaBeta()); CHECK_EQUAL(0, tcplq.getRho()); CHECK_EQUAL(0, tcplq.getValue()); tcplq = rttb::models::TCPLQModel(dvhPtr, roh, numFractions, alpha / beta, alpha, 0.08); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alpha / beta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); CHECK_EQUAL(0, tcplq.getValue()); tcplq = rttb::models::TCPLQModel(); CHECK_EQUAL(0, tcplq.getAlphaMean()); CHECK_EQUAL(0, tcplq.getAlphaBeta()); CHECK_EQUAL(0, tcplq.getRho()); CHECK_EQUAL(0, tcplq.getValue()); tcplq = rttb::models::TCPLQModel(dvhPtr, alpha, beta, roh, numFractions); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(alpha / beta, tcplq.getAlphaBeta()); CHECK_EQUAL(roh, tcplq.getRho()); CHECK_EQUAL(0, tcplq.getValue()); //2) test init (calcTCPxxx) CHECK_NO_THROW(tcplq.init(1)); //3) test set/get CHECK_EQUAL(0, tcplq.getValue()); CHECK_NO_THROW(tcplq.setParameters(alpha, 10, roh, 0.08)); CHECK_EQUAL(10, tcplq.getAlphaBeta()); CHECK_EQUAL(0.08, tcplq.getAlphaVariance()); CHECK_EQUAL(alpha, tcplq.getAlphaMean()); CHECK_EQUAL(roh, tcplq.getRho()); CHECK_NO_THROW(models::getCurveDoseVSBioModel(tcplq, normalizationDose)); std::vector aParameterVector; aParameterVector.push_back(alpha + 0.02); CHECK_THROW_EXPLICIT(tcplq.setParameterVector(aParameterVector), core::InvalidParameterException); aParameterVector.push_back(0.06); aParameterVector.push_back(8); aParameterVector.push_back(roh / 10); CHECK_NO_THROW(tcplq.setParameterVector(aParameterVector)); CHECK_EQUAL(8, tcplq.getAlphaBeta()); CHECK_EQUAL(0.06, tcplq.getAlphaVariance()); CHECK_EQUAL(alpha + 0.02, tcplq.getAlphaMean()); CHECK_EQUAL(roh / 10, tcplq.getRho()); for (int i = 0; i < 4; i++) { CHECK_NO_THROW(tcplq.setParameterByID(i, models::BioModelParamType(i))); } CHECK_THROW_EXPLICIT(tcplq.setParameterByID(4, 4.0), core::InvalidParameterException); CHECK_EQUAL(0, tcplq.getParameterID("alphaMean")); CHECK_EQUAL(0, tcplq.getAlphaMean()); CHECK_EQUAL(1, tcplq.getParameterID("alphaVariance")); CHECK_EQUAL(1, tcplq.getAlphaVariance()); CHECK_EQUAL(2, tcplq.getParameterID("alpha_beta")); CHECK_EQUAL(2, tcplq.getAlphaBeta()); CHECK_EQUAL(3, tcplq.getParameterID("rho")); CHECK_EQUAL(3, tcplq.getRho()); //test NTCPLKBModel //1) test constructors (values as expected?) models::BioModelParamType aVal = 10; models::BioModelParamType mVal = 0.16; models::BioModelParamType d50Val = 35; CHECK_NO_THROW(rttb::models::NTCPLKBModel()); rttb::models::NTCPLKBModel lkb = rttb::models::NTCPLKBModel(); CHECK_EQUAL(0, lkb.getA()); CHECK_EQUAL(0, lkb.getM()); CHECK_EQUAL(0, lkb.getD50()); CHECK_EQUAL(0, lkb.getValue()); CHECK_NO_THROW(rttb::models::NTCPLKBModel(dvhPtr, d50Val, mVal, aVal)); lkb = rttb::models::NTCPLKBModel(dvhPtr, d50Val, mVal, aVal); CHECK_EQUAL(0, lkb.getValue()); CHECK_EQUAL(dvhPtr, lkb.getDVH()); CHECK_EQUAL(aVal, lkb.getA()); CHECK_EQUAL(mVal, lkb.getM()); CHECK_EQUAL(d50Val, lkb.getD50()); //2) test init (calcxxx) CHECK_NO_THROW(lkb.init(1)); lkb.getValue(); //3) test set/get lkb = rttb::models::NTCPLKBModel(); CHECK_EQUAL(0, lkb.getA()); CHECK_EQUAL(0, lkb.getM()); CHECK_EQUAL(0, lkb.getD50()); lkb.setDVH(dvhPtr); CHECK_EQUAL(dvhPtr, lkb.getDVH()); lkb.setA(aVal); CHECK_EQUAL(aVal, lkb.getA()); lkb.setM(mVal); CHECK_EQUAL(mVal, lkb.getM()); lkb.setD50(d50Val); CHECK_EQUAL(d50Val, lkb.getD50()); CHECK_NO_THROW(models::getCurveEUDVSBioModel(lkb)); aParameterVector.clear(); aParameterVector.push_back(d50Val + 5); CHECK_THROW_EXPLICIT(lkb.setParameterVector(aParameterVector), core::InvalidParameterException); aParameterVector.push_back(mVal + 0.2); aParameterVector.push_back(aVal + 0.5); CHECK_NO_THROW(lkb.setParameterVector(aParameterVector)); CHECK_EQUAL(aVal + 0.5, lkb.getA()); CHECK_EQUAL(mVal + 0.2, lkb.getM()); CHECK_EQUAL(d50Val + 5, lkb.getD50()); for (int i = 0; i < 3; i++) { CHECK_NO_THROW(lkb.setParameterByID(i, models::BioModelParamType(i))); } CHECK_THROW_EXPLICIT(lkb.setParameterByID(3, 4.0), core::InvalidParameterException); CHECK_EQUAL(0, lkb.getParameterID("d50")); CHECK_EQUAL(0, lkb.getD50()); CHECK_EQUAL(1, lkb.getParameterID("m")); CHECK_EQUAL(1, lkb.getM()); CHECK_EQUAL(2, lkb.getParameterID("a")); CHECK_EQUAL(2, lkb.getA()); //test NTCPRSModel //1) test constructors (values as expected?) CHECK_NO_THROW(rttb::models::NTCPRSModel()); models::BioModelParamType gammaVal = 1.7; models::BioModelParamType sVal = 1; CHECK_NO_THROW(rttb::models::NTCPRSModel(dvhPtr, d50Val, gammaVal, sVal)); rttb::models::NTCPRSModel rs = rttb::models::NTCPRSModel(dvhPtr, d50Val, gammaVal, sVal); CHECK_EQUAL(dvhPtr, rs.getDVH()); CHECK_EQUAL(d50Val, rs.getD50()); CHECK_EQUAL(gammaVal, rs.getGamma()); CHECK_EQUAL(sVal, rs.getS()); rs = rttb::models::NTCPRSModel(); CHECK_EQUAL(0, rs.getGamma()); CHECK_EQUAL(0, rs.getS()); CHECK_EQUAL(0, rs.getD50()); //3) test set/get rs.setDVH(dvhPtr); CHECK_EQUAL(dvhPtr, rs.getDVH()); rs.setD50(d50Val); CHECK_EQUAL(d50Val, rs.getD50()); rs.setGamma(gammaVal); CHECK_EQUAL(gammaVal, rs.getGamma()); rs.setS(sVal); CHECK_EQUAL(sVal, rs.getS()); //2) test init (calcxxx) CHECK_NO_THROW(rs.init(1)); //3) test set/get continued aParameterVector.clear(); aParameterVector.push_back(d50Val + 5); CHECK_THROW_EXPLICIT(rs.setParameterVector(aParameterVector), core::InvalidParameterException); aParameterVector.push_back(gammaVal + 0.2); aParameterVector.push_back(sVal + 0.5); CHECK_NO_THROW(rs.setParameterVector(aParameterVector)); CHECK_EQUAL(gammaVal + 0.2, rs.getGamma()); CHECK_EQUAL(sVal + 0.5, rs.getS()); CHECK_EQUAL(d50Val + 5, rs.getD50()); for (int i = 0; i < 3; i++) { CHECK_NO_THROW(rs.setParameterByID(i, models::BioModelParamType(i))); } CHECK_THROW_EXPLICIT(rs.setParameterByID(3, 4.0), core::InvalidParameterException); CHECK_EQUAL(0, rs.getParameterID("d50")); CHECK_EQUAL(0, rs.getD50()); CHECK_EQUAL(1, rs.getParameterID("gamma")); CHECK_EQUAL(1, rs.getGamma()); CHECK_EQUAL(2, rs.getParameterID("s")); CHECK_EQUAL(2, rs.getS()); //Scatter plot tests CHECK_NO_THROW(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, 0, normalizationDose)); //variance=0, will be set to 1e-30 CHECK_THROW_EXPLICIT(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, alpha * 0.1, 0), core::InvalidParameterException);//normalisationdose=0 CHECK_THROW_EXPLICIT(models::getScatterPlotVary1Parameter(tcplq, 0, alpha, alpha * 0.1, normalizationDose, 10000, 0, 0), core::InvalidParameterException);//maxDose-minDose=0 RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/models/DvhBasedModelsTest.cpp b/testing/models/DvhBasedModelsTest.cpp index 318bc4d..c4ef949 100644 --- a/testing/models/DvhBasedModelsTest.cpp +++ b/testing/models/DvhBasedModelsTest.cpp @@ -1,105 +1,103 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include -#include #include "litCheckMacros.h" -#include "rttbDVH.h" #include "rttbDvhBasedModels.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { typedef core::DVH::DataDifferentialType DataDifferentialType; /*! @brief DvhBasedModelsTest. 1) Test bed und lqed2 */ int DvhBasedModelsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) test calcBEDDVH and calcLQED2DVH //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; const IDType structureID = "myStructure"; const IDType doseID = "myDose"; const IDType voxelizationID = "myVoxelization"; DataDifferentialType aDataDifferential; std::vector bedVector; std::vector lqed2Vector; int numberOfFractions = 2; double alpha_beta = 10; for (int i = 0; i < 100; i++) { double volume = DoseCalcType((double(rand()) / RAND_MAX) * 1000); double dose = (i + 0.5) * binSize; aDataDifferential.push_back(volume); bedVector.push_back(dose * (1 + dose / (numberOfFractions * alpha_beta))); lqed2Vector.push_back(dose * ((alpha_beta + (dose / numberOfFractions)) / (alpha_beta + 2))); } core::DVH myDVH(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); core::DVH::Pointer dvhPtr = boost::make_shared(myDVH); CHECK_THROW_EXPLICIT(rttb::models::calcBEDDVH(dvhPtr, 0, 10), core::InvalidParameterException); CHECK_THROW_EXPLICIT(rttb::models::calcBEDDVH(dvhPtr, 10, -1), core::InvalidParameterException); CHECK_NO_THROW(rttb::models::calcBEDDVH(dvhPtr, 10, 10)); CHECK_EQUAL(rttb::models::calcBEDDVH(dvhPtr, 2, 10).size(), myDVH.getDataDifferential().size()); rttb::models::BEDDVHType bedDVH = rttb::models::calcBEDDVH(dvhPtr, numberOfFractions, alpha_beta); CHECK_THROW_EXPLICIT(rttb::models::calcLQED2DVH(dvhPtr, 1, 10), core::InvalidParameterException); CHECK_THROW_EXPLICIT(rttb::models::calcLQED2DVH(dvhPtr, 10, -1), core::InvalidParameterException); CHECK_NO_THROW(rttb::models::calcLQED2DVH(dvhPtr, 10, 10, true)); CHECK_EQUAL(rttb::models::calcLQED2DVH(dvhPtr, 2, 10).size(), myDVH.getDataDifferential().size()); rttb::models::BEDDVHType lqed2DVH = rttb::models::calcLQED2DVH(dvhPtr, numberOfFractions, alpha_beta); //check the calculation rttb::models::BEDDVHType::iterator itBED, itLQED2; std::vector::iterator itBEDVec, itLQED2Vec; DataDifferentialType::iterator itDiff; for (itBED = bedDVH.begin(), itLQED2 = lqed2DVH.begin(), itBEDVec = bedVector.begin(), itLQED2Vec = lqed2Vector.begin(), itDiff = aDataDifferential.begin(); itBED != bedDVH.end(), itLQED2 != lqed2DVH.end(), itBEDVec != bedVector.end(), itLQED2Vec != lqed2Vector.end(), itDiff != aDataDifferential.end(); ++itBED, ++itLQED2, ++itBEDVec, ++itLQED2Vec, ++itDiff) { //check volume CHECK_EQUAL(*itDiff, (*itBED).second); CHECK_EQUAL((*itBED).second, (*itLQED2).second); //check bed CHECK_EQUAL(*itBEDVec, (*itBED).first); //check lqed2 CHECK_EQUAL(*itLQED2Vec, (*itLQED2).first); } RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/validation/VoxelizationDVHComparisonTest.cpp b/testing/validation/VoxelizationDVHComparisonTest.cpp index 6d4aa17..0c9ae74 100644 --- a/testing/validation/VoxelizationDVHComparisonTest.cpp +++ b/testing/validation/VoxelizationDVHComparisonTest.cpp @@ -1,170 +1,166 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 -#include "litCheckMacros.h" - #include "rttbGenericMaskedDoseIterator.h" #include "rttbGenericDoseIterator.h" -#include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbDVHCalculator.h" #include "rttbBoostMaskAccessor.h" #include "rttbDVHXMLFileWriter.h" #include "rttbDVHXMLFileReader.h" #include "../io/other/CompareDVH.h" namespace rttb { namespace testing { /*! @brief VoxelizationDVHComparisonTests. Computes the DVH difference of different voxelizations (OTB/Boost legacy/Boost) Writes the difference in a DVH and saves in a file */ core::DoseIteratorInterface::Pointer createMaskDoseIterator(masks::boost::BoostMaskAccessor::StructTypePointer rtstruct, core::GenericDoseIterator::DoseAccessorPointer doseAccessor, const std::string& voxelizationType) { core::GenericMaskedDoseIterator::MaskAccessorPointer spMaskAccessor; if (voxelizationType == "Boost"){ auto spBoostRedesignMaskAccessor = ::boost::make_shared(rtstruct, doseAccessor->getGeometricInfo()); spBoostRedesignMaskAccessor->updateMask(); spMaskAccessor = spBoostRedesignMaskAccessor; } auto spMaskedDoseIteratorTmp = ::boost::make_shared(spMaskAccessor, doseAccessor); core::DoseIteratorInterface::Pointer spMaskedDoseIterator(spMaskedDoseIteratorTmp); return spMaskedDoseIterator; } rttb::core::DVH calcDVH(core::DVHCalculator::DoseIteratorPointer doseIterator, const IDType& structUID, const IDType& doseUID) { rttb::core::DVHCalculator calc(doseIterator, structUID, doseUID); rttb::core::DVH dvh = *(calc.generateDVH()); return dvh; } void writeCumulativeDVH(const std::string& filename, rttb::core::DVH dvh) { DVHType typeCum = { DVHType::Cumulative }; io::other::DVHXMLFileWriter dvhWriter(filename, typeCum); dvhWriter.writeDVH(boost::make_shared(dvh)); } int VoxelizationDVHComparisonTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::StructureSet::Pointer StructureSetPointer; PREPARE_DEFAULT_TEST_REPORTING; std::string RTSTRUCT_FILENAME; std::string RTDOSE_FILENAME; std::string RTDVH_XML_OTB_DIRECTORY; std::string RTDVH_XML_BOOST_LEGACY_DIRECTORY; std::string RTDVH_XML_BOOST_DIRECTORY; if (argc > 5) { RTSTRUCT_FILENAME = argv[1]; RTDOSE_FILENAME = argv[2]; RTDVH_XML_OTB_DIRECTORY = argv[3]; RTDVH_XML_BOOST_LEGACY_DIRECTORY = argv[4]; RTDVH_XML_BOOST_DIRECTORY = argv[5]; } // read dicom-rt dose io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //create a vector of MaskAccessors (one for each structure) StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTSTRUCT_FILENAME.c_str()).generateStructureSet(); //create directory boost::filesystem::create_directories(RTDVH_XML_BOOST_DIRECTORY); //start evaluation clock_t start(clock()); if (rtStructureSet->getNumberOfStructures() > 0) { for (int j = 0; j < static_cast(rtStructureSet->getNumberOfStructures()); j++) { std::cout << rtStructureSet->getStructure(j)->getLabel() << std::endl; auto spMaskedDoseIteratorBoostRedesign = createMaskDoseIterator(rtStructureSet->getStructure(j), doseAccessor1, "Boost"); auto label = rtStructureSet->getStructure(j)->getLabel(); ::boost::replace_all(label, "/", "_"); boost::filesystem::path dvhOTBFilename(RTDVH_XML_OTB_DIRECTORY); dvhOTBFilename /= "DVH_" + label + ".xml"; boost::filesystem::path dvhBoostFilename(RTDVH_XML_BOOST_LEGACY_DIRECTORY); dvhBoostFilename /= "DVH_" + label + ".xml"; io::other::DVHXMLFileReader dvhReaderOTB(dvhOTBFilename.string()); auto dvhOTB = dvhReaderOTB.generateDVH(); io::other::DVHXMLFileReader dvhReaderBoost(dvhBoostFilename.string()); auto dvhBoost = dvhReaderBoost.generateDVH(); auto dvhBoostRedesign = calcDVH(spMaskedDoseIteratorBoostRedesign, (rtStructureSet->getStructure(j))->getUID(), doseAccessor1->getUID()); boost::filesystem::path dvhBoostRedesignFilename(RTDVH_XML_BOOST_DIRECTORY); dvhBoostRedesignFilename /= "DVH_" + label + ".xml"; writeCumulativeDVH(dvhBoostRedesignFilename.string(), dvhBoostRedesign); std::cout << "=== Dose 1 Structure " << j << "===" << std::endl; std::cout << "with OTB voxelization: " << std::endl; std::cout << dvhOTB << std::endl; std::cout << "with Boost_LEGACY voxelization: " << std::endl; std::cout << dvhBoost << std::endl; std::cout << "with Boost voxelization: " << std::endl; std::cout << dvhBoostRedesign << std::endl; //compare DVH for different voxelizations auto diffDVH = computeDiffDVH(dvhOTB, boost::make_shared(dvhBoostRedesign)); boost::filesystem::path dvhBoostRedesignDiffFilename(RTDVH_XML_BOOST_DIRECTORY); dvhBoostRedesignDiffFilename /= "DVHDiff_" + label + ".xml"; writeCumulativeDVH(dvhBoostRedesignDiffFilename.string(), *diffDVH); } } clock_t finish(clock()); std::cout << "DVH Calculation time: " << finish - start << " ms" << std::endl; RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/validation/VoxelizationValidationTest.cpp b/testing/validation/VoxelizationValidationTest.cpp index 55224bb..589eb31 100644 --- a/testing/validation/VoxelizationValidationTest.cpp +++ b/testing/validation/VoxelizationValidationTest.cpp @@ -1,154 +1,147 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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 "rttbGenericMaskedDoseIterator.h" #include "rttbGenericDoseIterator.h" -#include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbBoostMaskAccessor.h" #include "rttbITKImageMaskAccessorConverter.h" #include "rttbImageWriter.h" #include "rttbBoostMask.h" -#include "rttbBoostMaskAccessor.h" -#include "rttbITKImageAccessorGenerator.h" -#include "rttbITKImageFileAccessorGenerator.h" -#include "rttbInvalidParameterException.h" #include "itkSubtractImageFilter.h" #include "itkImageFileReader.h" namespace rttb { namespace testing { io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer subtractImages(const io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer image1, const io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer image2) { typedef itk::SubtractImageFilter SubtractImageFilterType; SubtractImageFilterType::Pointer subtractFilter = SubtractImageFilterType::New(); subtractFilter->SetInput1(image1); subtractFilter->SetInput2(image2); //since the image origin may be modified through the writing process a bit subtractFilter->SetCoordinateTolerance(5e-2); subtractFilter->Update(); return subtractFilter->GetOutput(); } /*! @brief VoxelizationValidationTest. Compare the new boost voxelization to the OTB voxelization Check the creating of new boost masks for files where the old boost voxelization failed. */ int VoxelizationValidationTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::StructureSet::Pointer StructureSetPointer; std::string RTSTRUCT_FILENAME; std::string RTDOSE_FILENAME; std::string BoostMask_DIRNAME; std::string OTBMask_DIRNAME; if (argc > 4) { RTSTRUCT_FILENAME = argv[1]; RTDOSE_FILENAME = argv[2]; BoostMask_DIRNAME = argv[3]; OTBMask_DIRNAME = argv[4]; } //create directory boost::filesystem::create_directories(BoostMask_DIRNAME); /* read dicom-rt dose */ io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //create a vector of MaskAccessors (one for each structure) StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTSTRUCT_FILENAME.c_str()).generateStructureSet(); if (rtStructureSet->getNumberOfStructures() > 0) { //do not compute structure "Aussenkontur" since it is very large (15000 cm³) for (size_t j = 1; j < rtStructureSet->getNumberOfStructures(); j++) { std::cout << j << ": " << rtStructureSet->getStructure(j)->getLabel() << std::endl; //read OTB mask image boost::filesystem::path otbMaskFilename(OTBMask_DIRNAME); otbMaskFilename /= boost::lexical_cast(j)+".mhd"; typedef itk::ImageFileReader ReaderType; ReaderType::Pointer readerOTB = ReaderType::New(); readerOTB->SetFileName(otbMaskFilename.string()); readerOTB->Update(); const io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer otbMaskImage = readerOTB->GetOutput(); //create Boost MaskAccessor clock_t startR(clock()); MaskAccessorPointer boostMaskRPtr = ::boost::make_shared (rtStructureSet->getStructure(j), doseAccessor1->getGeometricInfo()); CHECK_NO_THROW(boostMaskRPtr->updateMask()); clock_t finishR(clock()); std::cout << "Boost Mask Calculation: " << finishR - startR << " ms" << std::endl; rttb::io::itk::ITKImageMaskAccessorConverter itkConverterR(boostMaskRPtr); CHECK(itkConverterR.process()); boost::filesystem::path redesignFilename(BoostMask_DIRNAME); redesignFilename /= boost::lexical_cast(j)+".nrrd"; rttb::io::itk::ImageWriter writerR(redesignFilename.string(), itkConverterR.getITKImage().GetPointer()); CHECK(writerR.writeFile()); auto subtractedRedesignImage = subtractImages(otbMaskImage, itkConverterR.getITKImage()); boost::filesystem::path subtractRedesignFilename(BoostMask_DIRNAME); subtractRedesignFilename /= boost::lexical_cast(j)+"_subtracted.nrrd"; rttb::io::itk::ImageWriter writerRSubtracted(subtractRedesignFilename.string(), subtractedRedesignImage.GetPointer()); CHECK(writerRSubtracted.writeFile()); } } RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/validation/rttbValidationTests.cpp b/testing/validation/rttbValidationTests.cpp index 5575cb1..4d9e575 100644 --- a/testing/validation/rttbValidationTests.cpp +++ b/testing/validation/rttbValidationTests.cpp @@ -1,58 +1,56 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ // 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" -#include "RTToolboxConfigure.h" - namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(VoxelizationDVHComparisonTest); LIT_REGISTER_TEST(VoxelizationValidationTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (const std::exception& /*e*/) { result = -1; } catch (...) { result = -1; } return result; }