From bee7e8bb7530def87a4cff07273d69b8959e3142 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 6 Dec 2024 17:21:27 +0100 Subject: [PATCH 1/5] IO/IOSS/Testing: remove stray comma in source list (cherry picked from commit ecf159e0115b46561fb66b3ce8b59778ae01140e) --- IO/IOSS/Testing/Cxx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO/IOSS/Testing/Cxx/CMakeLists.txt b/IO/IOSS/Testing/Cxx/CMakeLists.txt index 6efb9f0eeedb..cbba4612e849 100644 --- a/IO/IOSS/Testing/Cxx/CMakeLists.txt +++ b/IO/IOSS/Testing/Cxx/CMakeLists.txt @@ -5,7 +5,7 @@ vtk_add_test_cxx(vtkIOIOSSCxxTests tests TestIOSSCGNS.cxx TestIOSSExodus.cxx,NO_VALID TestIOSSExodusMergeEntityBlocks.cxx,NO_VALID - TestIOSSExodusParallelWriter.cxx, + TestIOSSExodusParallelWriter.cxx TestIOSSExodusRestarts.cxx,NO_VALID TestIOSSExodusSetArrays.cxx TestIOSSExodusWriterCrinkleClip.cxx -- GitLab From c2eb7685fe32b85c5df24704af70d85b03d4b2fd Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 6 Dec 2024 17:21:41 +0100 Subject: [PATCH 2/5] TestIOSSExodusParallelWriter: fix compilation without MPI (cherry picked from commit d2b896454033cc01baf0e0b69893c7bccdd42b66) --- IO/IOSS/Testing/Cxx/TestIOSSExodusParallelWriter.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/IO/IOSS/Testing/Cxx/TestIOSSExodusParallelWriter.cxx b/IO/IOSS/Testing/Cxx/TestIOSSExodusParallelWriter.cxx index ea1eb34fac0a..4d327a1b100d 100644 --- a/IO/IOSS/Testing/Cxx/TestIOSSExodusParallelWriter.cxx +++ b/IO/IOSS/Testing/Cxx/TestIOSSExodusParallelWriter.cxx @@ -21,12 +21,12 @@ #include #include #include -#include #include #include #if VTK_MODULE_ENABLE_VTK_ParallelMPI #include +#include #else #include "vtkDummyController.h" #endif @@ -155,10 +155,12 @@ int TestIOSSExodusParallelWriter(int argc, char* argv[]) ren->ResetCamera(bds); ren->ResetCameraClippingRange(bds); +#if VTK_MODULE_ENABLE_VTK_ParallelMPI vtkNew syncWindows; syncWindows->SetRenderWindow(renWin); syncWindows->SetParallelController(contr); syncWindows->SetIdentifier(1); +#endif vtkNew syncRenderers; syncRenderers->SetRenderer(ren); -- GitLab From 4271d352028d34d9cc8a1656cc8c08353c6befb3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 6 Dec 2024 17:22:07 +0100 Subject: [PATCH 3/5] vtkTesting: fix string allocation `newFileName` is deleted using `delete[]`, so allocate it with `new[]`. (cherry picked from commit 058ac71c9acd78770573a510a34e774d8792bcd0) --- Testing/Rendering/vtkTesting.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Testing/Rendering/vtkTesting.cxx b/Testing/Rendering/vtkTesting.cxx index 1d26ae0ec461..fe83e0353171 100644 --- a/Testing/Rendering/vtkTesting.cxx +++ b/Testing/Rendering/vtkTesting.cxx @@ -845,7 +845,8 @@ int vtkTesting::RegressionTest(vtkAlgorithm* imageSource, double thresh, ostream vtkEmscriptenTestUtilities::PreloadDataFile(hostFileName.c_str(), sandboxedFileName); // so that subsequent code uses the sandboxed file name instead of host file name. delete[] newFileName; - newFileName = strdup(sandboxedFileName.c_str()); + newFileName = new char[sandboxedFileName.size() + 1]; + strcpy(newFileName, sandboxedFileName.c_str()); #endif if (!LookForFile(newFileName)) { @@ -972,7 +973,8 @@ int vtkTesting::RegressionTest(vtkAlgorithm* imageSource, double thresh, ostream #ifdef __EMSCRIPTEN__ std::string sandboxedFileName = vtkEmscriptenTestUtilities::PreloadDataFile(newFileName); delete[] newFileName; - newFileName = strdup(sandboxedFileName.c_str()); + newFileName = new char[sandboxedFileName.size() + 1]; + strcpy(newFileName, sandboxedFileName.c_str()); #endif rtPng->SetFileName(newFileName); delete[] newFileName; -- GitLab From 40064c9a6bfe0d71ff5cf82545f658fc82f40cc4 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 6 Dec 2024 17:22:36 +0100 Subject: [PATCH 4/5] vtkTesting: fix typo in log string (cherry picked from commit 4250a4d96f7f7f181ecda30059b77f4a9845537d) --- Testing/Rendering/vtkTesting.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/Rendering/vtkTesting.cxx b/Testing/Rendering/vtkTesting.cxx index fe83e0353171..f396a15952ba 100644 --- a/Testing/Rendering/vtkTesting.cxx +++ b/Testing/Rendering/vtkTesting.cxx @@ -867,7 +867,7 @@ int vtkTesting::RegressionTest(vtkAlgorithm* imageSource, double thresh, ostream if ((ext2[1] - ext2[0]) == (ext1[1] - ext1[0]) && (ext2[3] - ext2[2]) == (ext1[3] - ext1[2]) && (ext2[5] - ext2[4]) == (ext1[5] - ext1[4])) { - vtkLog(INFO, "Trying onother baseline."); + vtkLog(INFO, "Trying another baseline."); // Cannot compute difference unless image sizes are the same executeComparison(error); } -- GitLab From 13e0d68faab88d210d8fd9cddc43a112ad05e755 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 6 Dec 2024 18:53:30 +0100 Subject: [PATCH 5/5] vtkImageSSIM: handle SSIM's [-1,1] range When SSIM returns a negative value, the histogram bucketing ends up writing to out-of-bounds memory. Don't do that and instead shift the buckets to account for the full range of values that are possible. Finally, add commentary on the code. The clamping is still preserved as enabled by default in vtkTesting, because we want to treat the anti-correlated images (negative values) in the same way as not similar. --- Imaging/Core/vtkImageSSIM.cxx | 54 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/Imaging/Core/vtkImageSSIM.cxx b/Imaging/Core/vtkImageSSIM.cxx index 6f8ba9a079f4..8c695784b615 100644 --- a/Imaging/Core/vtkImageSSIM.cxx +++ b/Imaging/Core/vtkImageSSIM.cxx @@ -172,13 +172,16 @@ std::array ComputeMinkowski(vtkDoubleArray* array, double (*f)(double { for (int dim = 0; dim < 3; ++dim) { + // The range of ssim values is [-1, 1]. By doing 1 - value, we change the range to [0, 2] measure[dim] += f(1.0 - lab[dim]); } } + // Normalize the measure + const vtkIdType div = array->GetNumberOfTuples(); for (int dim = 0; dim < 3; ++dim) { - measure[dim] /= array->GetNumberOfTuples(); + measure[dim] /= div; } return measure; @@ -186,13 +189,14 @@ std::array ComputeMinkowski(vtkDoubleArray* array, double (*f)(double std::array ComputeMinkowski1(vtkDoubleArray* array) { - return ComputeMinkowski(array, &std::abs); + auto same = [](double v) -> double { return v; }; + return ComputeMinkowski(array, same); } std::array ComputeMinkowski2(vtkDoubleArray* array) { - auto f = [](double v) { return v * v; }; - auto measure = ComputeMinkowski(array, f); + auto power2 = [](double v) -> double { return v * v; }; + auto measure = ComputeMinkowski(array, power2); for (int dim = 0; dim < 3; ++dim) { measure[dim] = std::sqrt(measure[dim]); @@ -200,34 +204,47 @@ std::array ComputeMinkowski2(vtkDoubleArray* array) return measure; } -std::array ComputeWasserstein(vtkDoubleArray* array, double (*f)(double)) +std::array ComputeWasserstein(vtkDoubleArray* array, std::uint64_t (*f)(std::uint64_t)) { std::array measure = {}; auto data = vtk::DataArrayTupleRange<3>(array); - constexpr int N = 100; - std::array hist[3] = {}; + constexpr std::uint64_t N = 200; + std::array hist[3] = {}; for (auto lab : data) { for (int dim = 0; dim < 3; ++dim) { - ++hist[dim][std::round(lab[dim] * (N - 1))]; + // The range of ssim values is [-1, 1], so we rescale it to [0, 1] + double value = (lab[dim] + 1.0) / 2.0; + // Find the bucket to place the value in, by rescaling it to [0, N - 1] + // [0, (N - 1) / 2] is for negative ssim values, + // N / 2 is for ssim = 0, + // ((N + 1) / 2, N - 1] is for positive ssim values + auto bucket = static_cast(std::round(value * (N - 1))); + ++hist[dim][bucket]; } } for (int dim = 0; dim < 3; ++dim) { - std::array cfd; + // Compute the cumulative frequency distribution + std::array cfd; std::partial_sum(hist[dim].begin(), hist[dim].end(), cfd.begin()); for (std::size_t i = 0; i < N - 1; ++i) { measure[dim] += f(cfd[i]); } + } - measure[dim] += f(cfd.back() - array->GetNumberOfTuples()); + // Normalize the measure + const vtkIdType div = f(static_cast(array->GetNumberOfTuples())) * (N - 1); + for (int dim = 0; dim < 3; ++dim) + { + measure[dim] /= div; } return measure; @@ -235,23 +252,16 @@ std::array ComputeWasserstein(vtkDoubleArray* array, double (*f)(doub std::array ComputeWasserstein1(vtkDoubleArray* array) { - auto measure = ComputeWasserstein(array, &std::abs); - vtkIdType div = array->GetNumberOfTuples() * (100 - 1); - for (int dim = 0; dim < 3; ++dim) - { - measure[dim] /= div; - } - return measure; + auto same = [](std::uint64_t v) -> std::uint64_t { return v; }; + return ComputeWasserstein(array, same); } std::array ComputeWasserstein2(vtkDoubleArray* array) { - auto f = [](double v) { return v * v; }; - auto measure = ComputeWasserstein(array, f); - vtkIdType div = array->GetNumberOfTuples() * array->GetNumberOfTuples() * (100 - 1); + auto power2 = [](std::uint64_t v) -> std::uint64_t { return v * v; }; + auto measure = ComputeWasserstein(array, power2); for (int dim = 0; dim < 3; ++dim) { - measure[dim] /= div; measure[dim] = std::sqrt(measure[dim]); } return measure; @@ -259,7 +269,7 @@ std::array ComputeWasserstein2(vtkDoubleArray* array) } // anonymous namespace //------------------------------------------------------------------------------ -// Construct object to extract all of the input data. +// Construct object to extract all the input data. vtkImageSSIM::vtkImageSSIM() { this->SetNumberOfInputPorts(2); -- GitLab