diff --git a/examples/gammaSimple.cpp b/examples/gammaSimple.cpp index b1d6a2d..5bd7f53 100644 --- a/examples/gammaSimple.cpp +++ b/examples/gammaSimple.cpp @@ -36,23 +36,8 @@ #include -void printImage2D(const yagit::Image2D& img){ - std::ostringstream oss; - oss << "["; - for(size_t i = 0; i < img.size(); i++){ - oss << (i == 0 ? "[" : " ["); - for(size_t j = 0; j < img[i].size() - 1; j++){ - oss << img[i][j] << ", "; - } - oss << img[i].back(); - oss << (i < img.size() - 1 ? "],\n" : "]"); - } - oss << "]\n"; - std::cout << oss.str(); -} - void printImageData(const yagit::ImageData& imageData){ - printImage2D(imageData.getImage2D(0)); + std::cout << yagit::image2DToString(imageData.getImage2D(0), 2) << "\n"; yagit::DataSize size = imageData.getSize(); yagit::DataOffset offset = imageData.getOffset(); @@ -105,10 +90,10 @@ int main(){ // print the gamma index image // expected: - // [[0.471405, 0.57735], - // [1.10554, 0.816496]] + // [[0.471, 0.577], + // [1.106, 0.816]] std::cout << "Gamma index image:\n"; - printImage2D(gammaRes.getImage2D(0)); + std::cout << yagit::image2DToString(gammaRes.getImage2D(0), 3) << "\n"; // print gamma index statistics std::cout << "GIPR: " << gammaRes.passingRate() * 100 << "%\n" diff --git a/include/yagit/Image.hpp b/include/yagit/Image.hpp index 46188dd..3c7fd56 100644 --- a/include/yagit/Image.hpp +++ b/include/yagit/Image.hpp @@ -19,6 +19,7 @@ #pragma once #include +#include namespace yagit{ @@ -32,6 +33,24 @@ using Image2D = std::vector>; */ using Image3D = std::vector; +/** + * @brief Convert Image2D to string + * @param img Image2D to convert + * @param precision Round numbers to @a precision digits after the decimal point. + * When set to a negative number, conversion precision has a default behavior. + * @return String representation of Image2D + */ +std::string image2DToString(const yagit::Image2D& img, std::streamsize precision = -1); + +/** + * @brief Convert Image3D to string + * @param img Image3D to convert + * @param precision Round numbers to @a precision digits after the decimal point. + * When set to a negative number, conversion precision has a default behavior. + * @return String representation of Image3D + */ +std::string image3DToString(const yagit::Image3D& img, std::streamsize precision = -1); + /** * @brief Axis of image (Z, Y, X) */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6a1194..b24dd09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ option(ENABLE_FMA "Enable fused multiply-add (FMA) when building yagit library" find_package(GDCM REQUIRED) set(YAGIT_SOURCE_FILES + Image.cpp ImageData.cpp GammaResult.cpp DataReader.cpp diff --git a/src/Image.cpp b/src/Image.cpp new file mode 100644 index 0000000..007c429 --- /dev/null +++ b/src/Image.cpp @@ -0,0 +1,63 @@ +/******************************************************************************************** + * Copyright (C) 2024 'Yet Another Gamma Index Tool' Developers. + * + * This file is part of 'Yet Another Gamma Index Tool'. + * + * 'Yet Another Gamma Index Tool' is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * 'Yet Another Gamma Index Tool' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 'Yet Another Gamma Index Tool'. If not, see . + ********************************************************************************************/ + +#include "yagit/Image.hpp" + +#include +#include + +namespace yagit{ + +namespace{ +std::string imageNDimToString(const std::vector& vector, std::streamsize precision = -1, uint32_t = 0){ + std::ostringstream oss; + if(precision > 0){ + oss << std::fixed << std::setprecision(precision); + } + oss << "["; + for(size_t i = 0; i < vector.size() - 1; i++){ + oss << vector[i] << ", "; + } + oss << vector.back() << "]"; + return oss.str(); +} + +template +std::string imageNDimToString(const std::vector& vector, std::streamsize precision = -1, uint32_t level = 0){ + std::string spaces(level + 1, ' '); + std::string res = ""; + res += "["; + for(size_t i = 0; i < vector.size() - 1; i++){ + res += imageNDimToString(vector[i], precision, level + 1) + ",\n" + spaces; + } + res += imageNDimToString(vector.back(), precision, level + 1); + res += "]"; + return res; +} +} + +std::string image2DToString(const yagit::Image2D& img, std::streamsize precision){ + return imageNDimToString(img, precision); +} + +std::string image3DToString(const yagit::Image3D& img, std::streamsize precision){ + return imageNDimToString(img, precision); +} + +} diff --git a/tests/manual/simulatedWendling.cpp b/tests/manual/simulatedWendling.cpp index 24a0833..522545e 100644 --- a/tests/manual/simulatedWendling.cpp +++ b/tests/manual/simulatedWendling.cpp @@ -76,38 +76,12 @@ const yagit::ImageData EVAL_3D(EVAL_IMAGE_3D, {-0.3, -6.0, 4.5}, {1.5, 2, 2.5}); // ==================================================================================================== -const std::streamsize PRECISION = 6; - -std::string imageNDimToStr(const std::vector& vector, uint32_t){ - std::ostringstream oss; - oss << std::fixed << std::setprecision(PRECISION); - oss << "["; - for(size_t i = 0; i < vector.size() - 1; i++){ - oss << vector[i] << ", "; - } - oss << vector.back() << "]"; - return oss.str(); -} - -template -std::string imageNDimToStr(const std::vector& vector, uint32_t level){ - std::string spaces(level + 1, ' '); - std::string res = ""; - res += "["; - for(size_t i = 0; i < vector.size() - 1; i++){ - res += imageNDimToStr(vector[i], level + 1) + ",\n" + spaces; - } - res += imageNDimToStr(vector.back(), level + 1); - res += "]"; - return res; -} - void printImage(const yagit::ImageData& gammaRes){ if(gammaRes.getSize().frames == 1){ - std::cout << imageNDimToStr(gammaRes.getImage2D(0), 0) << "\n"; + std::cout << yagit::image2DToString(gammaRes.getImage2D(0), 6) << "\n"; } else{ - std::cout << imageNDimToStr(gammaRes.getImage3D(), 0) << "\n"; + std::cout << yagit::image3DToString(gammaRes.getImage3D(), 6) << "\n"; } } @@ -249,12 +223,12 @@ void wendling(std::string dim, const yagit::GammaParameters& gammaParams){ std::cout << dim << " #############################################\n"; - std::cout << "VALUES USING CLASSIC WITH INTERPOLATED EVAL:\n"; + std::cout << "SIMULATED WENDLING METHOD:\n"; auto resClassic = classicFunc(refImg, evalImg, gammaParams); printImage(resClassic); std::cout << "==============================\n"; - std::cout << "VALUES USING WENDLING:\n"; + std::cout << "REAL WENDLING METHOD:\n"; auto resWendling = wendlingFunc(refImg, evalImg, gammaParams); printImage(resWendling); @@ -286,7 +260,7 @@ void wendling3D(const yagit::ImageData& refImg, const yagit::ImageData& evalImg, const float MAX_REF_DOSE = -1; // set automatically max reference dose int main(){ - yagit::GammaParameters gammaParams{3, 3, yagit::GammaNormalization::Global, MAX_REF_DOSE, 0, 2, 0.3}; + yagit::GammaParameters gammaParams{3, 3, yagit::GammaNormalization::Global, MAX_REF_DOSE, 0, 10, 0.3}; try{ // 2D diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index da7e5a0..3ecba92 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -9,6 +9,7 @@ set(TESTS_SRCS GammaTest GammaCommonTest GammaResultTest + ImageTest ImageDataTest InterpolationTest ) diff --git a/tests/unit/ImageTest.cpp b/tests/unit/ImageTest.cpp new file mode 100644 index 0000000..a5f1a9f --- /dev/null +++ b/tests/unit/ImageTest.cpp @@ -0,0 +1,141 @@ +/******************************************************************************************** + * Copyright (C) 2024 'Yet Another Gamma Index Tool' Developers. + * + * This file is part of 'Yet Another Gamma Index Tool'. + * + * 'Yet Another Gamma Index Tool' is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * 'Yet Another Gamma Index Tool' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 'Yet Another Gamma Index Tool'. If not, see . + ********************************************************************************************/ + +#include "yagit/Image.hpp" + +#include + +#include + +namespace{ +const yagit::Image3D IMAGE = { + {{1.45364, 45.578234}, + {-0.34921, 999.876543}}, + {{-12.74829, 43.45903}, + {0, 9.999999}} +}; + +const yagit::Image3D IMAGE_SPECIAL_VALUES = { + {{std::numeric_limits::quiet_NaN(), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}} +}; + +const yagit::Image3D IMAGE_NONUNIFORM = { + {{1}, + {2, 3}, + {4, 5, 6}}, + {{7, 8, 9, 10}} +}; +} + +TEST(ImageTest, image2DToString){ + const std::string image2DStr = yagit::image2DToString(IMAGE[0]); + + const std::string expected = + "[[1.45364, 45.5782],\n" + " [-0.34921, 999.877]]"; + EXPECT_EQ(expected, image2DStr); +} + +TEST(ImageTest, image2DToStringWithPrecision){ + const std::string image2DStr = yagit::image2DToString(IMAGE[0], 2); + + const std::string expected = + "[[1.45, 45.58],\n" + " [-0.35, 999.88]]"; + EXPECT_EQ(expected, image2DStr); +} + +TEST(ImageTest, image2DToStringWithNegativePrecision){ + const std::string image2DStr = yagit::image2DToString(IMAGE[0], -2); + + const std::string expected = + "[[1.45364, 45.5782],\n" + " [-0.34921, 999.877]]"; + EXPECT_EQ(expected, image2DStr); +} + +TEST(ImageTest, image2DToStringForSpecialValues){ + const std::string image2DStr = yagit::image2DToString(IMAGE_SPECIAL_VALUES[0]); + + const std::string expected = "[[nan, inf, -inf]]"; + EXPECT_EQ(expected, image2DStr); +} + +TEST(ImageTest, image2DToStringForNonuniformImage){ + const std::string image2DStr = yagit::image2DToString(IMAGE_NONUNIFORM[0]); + + const std::string expected = + "[[1],\n" + " [2, 3],\n" + " [4, 5, 6]]"; + EXPECT_EQ(expected, image2DStr); +} + +TEST(ImageTest, image3DToString){ + const std::string image3DStr = yagit::image3DToString(IMAGE); + + const std::string expected = + "[[[1.45364, 45.5782],\n" + " [-0.34921, 999.877]],\n" + " [[-12.7483, 43.459],\n" + " [0, 10]]]"; + EXPECT_EQ(expected, image3DStr); +} + +TEST(ImageTest, image3DToStringWithPrecision){ + const std::string image3DStr = yagit::image3DToString(IMAGE, 2); + + const std::string expected = + "[[[1.45, 45.58],\n" + " [-0.35, 999.88]],\n" + " [[-12.75, 43.46],\n" + " [0.00, 10.00]]]"; + EXPECT_EQ(expected, image3DStr); +} + +TEST(ImageTest, image3DToStringWithNegativePrecision){ + const std::string image3DStr = yagit::image3DToString(IMAGE, -2); + + const std::string expected = + "[[[1.45364, 45.5782],\n" + " [-0.34921, 999.877]],\n" + " [[-12.7483, 43.459],\n" + " [0, 10]]]"; + EXPECT_EQ(expected, image3DStr); +} + +TEST(ImageTest, image3DToStringForSpecialValues){ + const std::string image3DStr = yagit::image3DToString(IMAGE_SPECIAL_VALUES); + + const std::string expected = "[[[nan, inf, -inf]]]"; + EXPECT_EQ(expected, image3DStr); +} + +TEST(ImageTest, image3DToStringForNonuniformImage){ + const std::string image3DStr = yagit::image3DToString(IMAGE_NONUNIFORM); + + const std::string expected = + "[[[1],\n" + " [2, 3],\n" + " [4, 5, 6]],\n" + " [[7, 8, 9, 10]]]"; + EXPECT_EQ(expected, image3DStr); +}