Skip to content

Commit

Permalink
add image-to-string functions (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
michal367 authored Apr 25, 2024
1 parent d66344b commit 8e8a8f3
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 50 deletions.
23 changes: 4 additions & 19 deletions examples/gammaSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,8 @@

#include <yagit/yagit.hpp>

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();
Expand Down Expand Up @@ -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"
Expand Down
19 changes: 19 additions & 0 deletions include/yagit/Image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include <vector>
#include <string>

namespace yagit{

Expand All @@ -32,6 +33,24 @@ using Image2D = std::vector<std::vector<float>>;
*/
using Image3D = std::vector<Image2D>;

/**
* @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)
*/
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 63 additions & 0 deletions src/Image.cpp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
********************************************************************************************/

#include "yagit/Image.hpp"

#include <sstream>
#include <iomanip>

namespace yagit{

namespace{
std::string imageNDimToString(const std::vector<float>& 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 <typename T>
std::string imageNDimToString(const std::vector<T>& 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);
}

}
36 changes: 5 additions & 31 deletions tests/manual/simulatedWendling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<float>& 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 <typename T>
std::string imageNDimToStr(const std::vector<T>& 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";
}
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(TESTS_SRCS
GammaTest
GammaCommonTest
GammaResultTest
ImageTest
ImageDataTest
InterpolationTest
)
Expand Down
141 changes: 141 additions & 0 deletions tests/unit/ImageTest.cpp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
********************************************************************************************/

#include "yagit/Image.hpp"

#include <limits>

#include <gtest/gtest.h>

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<float>::quiet_NaN(),
std::numeric_limits<float>::infinity(),
-std::numeric_limits<float>::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);
}

0 comments on commit 8e8a8f3

Please sign in to comment.