From bda676e7d99d1dec51f6dd993d4a94ac8af8b930 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 11 Jul 2022 14:09:12 -0600 Subject: [PATCH] Consolidate UnitTestColorTable Previously, each device adapter implementation had their own version of this test by including a common header. Simplify this by making a single test in UnitTests_vtkm_cont_testing, which can now be compiled for and tested on a device. --- vtkm/cont/cuda/testing/CMakeLists.txt | 1 - .../cuda/testing/UnitTestCudaColorTable.cu | 20 - vtkm/cont/kokkos/testing/CMakeLists.txt | 1 - .../testing/UnitTestKokkosColorTable.cxx | 20 - vtkm/cont/openmp/testing/CMakeLists.txt | 1 - .../testing/UnitTestOpenMPColorTable.cxx | 19 - vtkm/cont/serial/testing/CMakeLists.txt | 1 - .../testing/UnitTestSerialColorTable.cxx | 20 - vtkm/cont/tbb/testing/CMakeLists.txt | 1 - .../tbb/testing/UnitTestTBBColorTable.cxx | 20 - vtkm/cont/testing/CMakeLists.txt | 2 +- vtkm/cont/testing/TestingColorTable.h | 526 ------------------ vtkm/cont/testing/UnitTestColorTable.cxx | 505 +++++++++++++++++ 13 files changed, 506 insertions(+), 631 deletions(-) delete mode 100644 vtkm/cont/cuda/testing/UnitTestCudaColorTable.cu delete mode 100644 vtkm/cont/kokkos/testing/UnitTestKokkosColorTable.cxx delete mode 100644 vtkm/cont/openmp/testing/UnitTestOpenMPColorTable.cxx delete mode 100644 vtkm/cont/serial/testing/UnitTestSerialColorTable.cxx delete mode 100644 vtkm/cont/tbb/testing/UnitTestTBBColorTable.cxx delete mode 100644 vtkm/cont/testing/TestingColorTable.h create mode 100644 vtkm/cont/testing/UnitTestColorTable.cxx diff --git a/vtkm/cont/cuda/testing/CMakeLists.txt b/vtkm/cont/cuda/testing/CMakeLists.txt index 22904beff..4ceb9e7a8 100644 --- a/vtkm/cont/cuda/testing/CMakeLists.txt +++ b/vtkm/cont/cuda/testing/CMakeLists.txt @@ -10,7 +10,6 @@ set(unit_tests UnitTestCudaComputeRange.cu - UnitTestCudaColorTable.cu UnitTestCudaDataSetExplicit.cu UnitTestCudaDataSetSingleType.cu UnitTestCudaDeviceAdapter.cu diff --git a/vtkm/cont/cuda/testing/UnitTestCudaColorTable.cu b/vtkm/cont/cuda/testing/UnitTestCudaColorTable.cu deleted file mode 100644 index 27940d221..000000000 --- a/vtkm/cont/cuda/testing/UnitTestCudaColorTable.cu +++ /dev/null @@ -1,20 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ - -#include - -#include - -int UnitTestCudaColorTable(int argc, char* argv[]) -{ - auto& tracker = vtkm::cont::GetRuntimeDeviceTracker(); - tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{}); - return vtkm::cont::testing::TestingColorTable::Run(argc, argv); -} diff --git a/vtkm/cont/kokkos/testing/CMakeLists.txt b/vtkm/cont/kokkos/testing/CMakeLists.txt index 15f4ea9ad..1c0dc843a 100644 --- a/vtkm/cont/kokkos/testing/CMakeLists.txt +++ b/vtkm/cont/kokkos/testing/CMakeLists.txt @@ -10,7 +10,6 @@ set(unit_tests UnitTestKokkosComputeRange.cxx - UnitTestKokkosColorTable.cxx UnitTestKokkosDataSetExplicit.cxx UnitTestKokkosDataSetSingleType.cxx UnitTestKokkosDeviceAdapter.cxx diff --git a/vtkm/cont/kokkos/testing/UnitTestKokkosColorTable.cxx b/vtkm/cont/kokkos/testing/UnitTestKokkosColorTable.cxx deleted file mode 100644 index f8c805a35..000000000 --- a/vtkm/cont/kokkos/testing/UnitTestKokkosColorTable.cxx +++ /dev/null @@ -1,20 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ - -#include -#include - -int UnitTestKokkosColorTable(int argc, char* argv[]) -{ - auto& tracker = vtkm::cont::GetRuntimeDeviceTracker(); - tracker.ForceDevice(vtkm::cont::DeviceAdapterTagKokkos{}); - return vtkm::cont::testing::TestingColorTable::Run(argc, - argv); -} diff --git a/vtkm/cont/openmp/testing/CMakeLists.txt b/vtkm/cont/openmp/testing/CMakeLists.txt index ec86ab2b3..a73d45d0f 100644 --- a/vtkm/cont/openmp/testing/CMakeLists.txt +++ b/vtkm/cont/openmp/testing/CMakeLists.txt @@ -9,7 +9,6 @@ ##============================================================================ set(unit_tests - UnitTestOpenMPColorTable.cxx UnitTestOpenMPComputeRange.cxx UnitTestOpenMPDataSetExplicit.cxx UnitTestOpenMPDataSetSingleType.cxx diff --git a/vtkm/cont/openmp/testing/UnitTestOpenMPColorTable.cxx b/vtkm/cont/openmp/testing/UnitTestOpenMPColorTable.cxx deleted file mode 100644 index f5ccede8a..000000000 --- a/vtkm/cont/openmp/testing/UnitTestOpenMPColorTable.cxx +++ /dev/null @@ -1,19 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ -#include -#include - -int UnitTestOpenMPColorTable(int argc, char* argv[]) -{ - auto& tracker = vtkm::cont::GetRuntimeDeviceTracker(); - tracker.ForceDevice(vtkm::cont::DeviceAdapterTagOpenMP{}); - return vtkm::cont::testing::TestingColorTable::Run(argc, - argv); -} diff --git a/vtkm/cont/serial/testing/CMakeLists.txt b/vtkm/cont/serial/testing/CMakeLists.txt index 15f07cba6..97f422cf0 100644 --- a/vtkm/cont/serial/testing/CMakeLists.txt +++ b/vtkm/cont/serial/testing/CMakeLists.txt @@ -10,7 +10,6 @@ set(unit_tests UnitTestSerialComputeRange.cxx - UnitTestSerialColorTable.cxx UnitTestSerialDataSetExplicit.cxx UnitTestSerialDataSetSingleType.cxx UnitTestSerialDeviceAdapter.cxx diff --git a/vtkm/cont/serial/testing/UnitTestSerialColorTable.cxx b/vtkm/cont/serial/testing/UnitTestSerialColorTable.cxx deleted file mode 100644 index 17b0e5a3d..000000000 --- a/vtkm/cont/serial/testing/UnitTestSerialColorTable.cxx +++ /dev/null @@ -1,20 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ - -#include - -#include - -int UnitTestSerialColorTable(int argc, char* argv[]) -{ - //TestingColorTable forces the device - return vtkm::cont::testing::TestingColorTable::Run(argc, - argv); -} diff --git a/vtkm/cont/tbb/testing/CMakeLists.txt b/vtkm/cont/tbb/testing/CMakeLists.txt index 6415b48d9..6c3268e87 100644 --- a/vtkm/cont/tbb/testing/CMakeLists.txt +++ b/vtkm/cont/tbb/testing/CMakeLists.txt @@ -9,7 +9,6 @@ ##============================================================================ set(unit_tests - UnitTestTBBColorTable.cxx UnitTestTBBComputeRange.cxx UnitTestTBBDataSetExplicit.cxx UnitTestTBBDataSetSingleType.cxx diff --git a/vtkm/cont/tbb/testing/UnitTestTBBColorTable.cxx b/vtkm/cont/tbb/testing/UnitTestTBBColorTable.cxx deleted file mode 100644 index f7216b451..000000000 --- a/vtkm/cont/tbb/testing/UnitTestTBBColorTable.cxx +++ /dev/null @@ -1,20 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ - -#include - -#include - -int UnitTestTBBColorTable(int argc, char* argv[]) -{ - auto& tracker = vtkm::cont::GetRuntimeDeviceTracker(); - tracker.ForceDevice(vtkm::cont::DeviceAdapterTagTBB{}); - return vtkm::cont::testing::TestingColorTable::Run(argc, argv); -} diff --git a/vtkm/cont/testing/CMakeLists.txt b/vtkm/cont/testing/CMakeLists.txt index 66cd7bfbe..425517a09 100644 --- a/vtkm/cont/testing/CMakeLists.txt +++ b/vtkm/cont/testing/CMakeLists.txt @@ -12,7 +12,6 @@ set(headers ExplicitTestData.h MakeTestDataSet.h Testing.h - TestingColorTable.h TestingComputeRange.h TestingDeviceAdapter.h TestingDataSetExplicit.h @@ -105,6 +104,7 @@ set(unit_tests_device UnitTestCellSetExplicit.cxx UnitTestCellSetExtrude.cxx UnitTestCellSetPermutation.cxx + UnitTestColorTable.cxx UnitTestDataSetPermutation.cxx UnitTestDeviceAdapterAlgorithmDependency.cxx UnitTestParticleArrayCopy.cxx diff --git a/vtkm/cont/testing/TestingColorTable.h b/vtkm/cont/testing/TestingColorTable.h deleted file mode 100644 index a6e058f17..000000000 --- a/vtkm/cont/testing/TestingColorTable.h +++ /dev/null @@ -1,526 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ -#ifndef vtk_m_cont_testing_TestingColorTable_h -#define vtk_m_cont_testing_TestingColorTable_h - -#include -#include -#include -#include -#include - -#include -#include - -namespace vtkm -{ -namespace cont -{ -namespace testing -{ - -template -class TestingColorTable -{ - - template - static void CheckColors(vtkm::cont::ArrayHandle> result, - const std::vector>& expected) - { - using Vec = vtkm::Vec; - - VTKM_TEST_ASSERT(result.GetNumberOfValues() == static_cast(expected.size())); - auto portal = result.ReadPortal(); - for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index) - { - Vec resultValue = portal.Get(index); - Vec expectedValue = expected[static_cast(index)]; - VTKM_TEST_ASSERT( - resultValue == expectedValue, "Expected color ", expectedValue, " but got ", resultValue); - } - } - -public: - static void TestConstructors() - { - vtkm::Range inValidRange{ 1.0, 0.0 }; - vtkm::Range range{ 0.0, 1.0 }; - vtkm::Vec rgb1{ 0.0f, 0.0f, 0.0f }; - vtkm::Vec rgb2{ 1.0f, 1.0f, 1.0f }; - auto rgbspace = vtkm::ColorSpace::RGB; - auto hsvspace = vtkm::ColorSpace::HSV; - auto diverging = vtkm::ColorSpace::Diverging; - - vtkm::cont::ColorTable table(rgbspace); - VTKM_TEST_ASSERT(table.GetColorSpace() == rgbspace, "color space not saved"); - VTKM_TEST_ASSERT(table.GetRange() == inValidRange, "default range incorrect"); - - vtkm::cont::ColorTable tableRGB(range, rgb1, rgb2, hsvspace); - VTKM_TEST_ASSERT(tableRGB.GetColorSpace() == hsvspace, "color space not saved"); - VTKM_TEST_ASSERT(tableRGB.GetRange() == range, "color range not saved"); - - vtkm::Vec rgba1{ 0.0f, 0.0f, 0.0f, 1.0f }; - vtkm::Vec rgba2{ 1.0f, 1.0f, 1.0f, 0.0f }; - vtkm::cont::ColorTable tableRGBA(range, rgba1, rgba2, diverging); - VTKM_TEST_ASSERT(tableRGBA.GetColorSpace() == diverging, "color space not saved"); - VTKM_TEST_ASSERT(tableRGBA.GetRange() == range, "color range not saved"); - - //verify we can store a vector of tables - std::vector tables; - tables.push_back(table); - tables.push_back(tableRGB); - tables.push_back(tableRGBA); - tables.push_back(tableRGBA); - tables.push_back(tableRGB); - tables.push_back(table); - } - - static void TestLoadPresets() - { - vtkm::Range range{ 0.0, 1.0 }; - auto rgbspace = vtkm::ColorSpace::RGB; - auto hsvspace = vtkm::ColorSpace::HSV; - auto labspace = vtkm::ColorSpace::Lab; - auto diverging = vtkm::ColorSpace::Diverging; - - { - vtkm::cont::ColorTable table(rgbspace); - VTKM_TEST_ASSERT(table.LoadPreset("Cool to Warm")); - VTKM_TEST_ASSERT(table.GetColorSpace() == diverging, - "color space not switched when loading preset"); - VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after loading preset"); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 3); - - VTKM_TEST_ASSERT(table.LoadPreset(vtkm::cont::ColorTable::Preset::CoolToWarmExtended)); - VTKM_TEST_ASSERT(table.GetColorSpace() == labspace, - "color space not switched when loading preset"); - VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after loading preset"); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 35); - - table.SetColorSpace(hsvspace); - VTKM_TEST_ASSERT((table.LoadPreset("no table with this name") == false), - "failed to error out on bad preset table name"); - //verify that after a failure we still have the previous preset loaded - VTKM_TEST_ASSERT(table.GetColorSpace() == hsvspace, - "color space not switched when loading preset"); - VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after failing preset"); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 35); - } - - - //verify that we can get the presets - std::set names = vtkm::cont::ColorTable::GetPresets(); - VTKM_TEST_ASSERT(names.size() == 18, "incorrect number of names in preset set"); - - VTKM_TEST_ASSERT(names.count("Inferno") == 1, "names should contain inferno"); - VTKM_TEST_ASSERT(names.count("Black-Body Radiation") == 1, - "names should contain black-body radiation"); - VTKM_TEST_ASSERT(names.count("Viridis") == 1, "names should contain viridis"); - VTKM_TEST_ASSERT(names.count("Black - Blue - White") == 1, - "names should contain black, blue and white"); - VTKM_TEST_ASSERT(names.count("Blue to Orange") == 1, "names should contain samsel fire"); - VTKM_TEST_ASSERT(names.count("Jet") == 1, "names should contain jet"); - - // verify that we can load in all the listed color tables - for (auto&& name : names) - { - vtkm::cont::ColorTable table(name); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() > 0, "Issue loading preset ", name); - } - - auto presetEnum = { vtkm::cont::ColorTable::Preset::Default, - vtkm::cont::ColorTable::Preset::CoolToWarm, - vtkm::cont::ColorTable::Preset::CoolToWarmExtended, - vtkm::cont::ColorTable::Preset::Viridis, - vtkm::cont::ColorTable::Preset::Inferno, - vtkm::cont::ColorTable::Preset::Plasma, - vtkm::cont::ColorTable::Preset::BlackBodyRadiation, - vtkm::cont::ColorTable::Preset::XRay, - vtkm::cont::ColorTable::Preset::Green, - vtkm::cont::ColorTable::Preset::BlackBlueWhite, - vtkm::cont::ColorTable::Preset::BlueToOrange, - vtkm::cont::ColorTable::Preset::GrayToRed, - vtkm::cont::ColorTable::Preset::ColdAndHot, - vtkm::cont::ColorTable::Preset::BlueGreenOrange, - vtkm::cont::ColorTable::Preset::YellowGrayBlue, - vtkm::cont::ColorTable::Preset::RainbowUniform, - vtkm::cont::ColorTable::Preset::Jet, - vtkm::cont::ColorTable::Preset::RainbowDesaturated }; - for (vtkm::cont::ColorTable::Preset preset : presetEnum) - { - vtkm::cont::ColorTable table(preset); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() > 0, "Issue loading preset"); - } - } - - static void TestClamping() - { - std::cout << "Test Clamping" << std::endl; - - vtkm::Range range{ 0.0, 1.0 }; - vtkm::Vec rgb1{ 0.0f, 1.0f, 0.0f }; - vtkm::Vec rgb2{ 1.0f, 0.0f, 1.0f }; - auto rgbspace = vtkm::ColorSpace::RGB; - - vtkm::cont::ColorTable table(range, rgb1, rgb2, rgbspace); - VTKM_TEST_ASSERT(table.GetClamping() == true, "clamping not setup properly"); - - auto field = vtkm::cont::make_ArrayHandle({ -1, 0, 1, 2 }); - - vtkm::cont::ArrayHandle colors; - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //verify that we clamp the values to the expected range - CheckColors(colors, { { 0, 255, 0 }, { 0, 255, 0 }, { 255, 0, 255 }, { 255, 0, 255 } }); - } - - static void TestRangeColors() - { - std::cout << "Test default ranges" << std::endl; - - vtkm::Range range{ -1.0, 2.0 }; - vtkm::Vec rgb1{ 0.0f, 1.0f, 0.0f }; - vtkm::Vec rgb2{ 1.0f, 0.0f, 1.0f }; - auto rgbspace = vtkm::ColorSpace::RGB; - - vtkm::cont::ColorTable table(range, rgb1, rgb2, rgbspace); - table.SetClampingOff(); - VTKM_TEST_ASSERT(table.GetClamping() == false, "clamping not setup properly"); - - auto field = vtkm::cont::make_ArrayHandle({ -2, -1, 2, 3 }); - - vtkm::cont::ArrayHandle colors; - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //verify that both the above and below range colors are used, - //and that the default value of both is 0,0,0 - CheckColors(colors, { { 0, 0, 0 }, { 0, 255, 0 }, { 255, 0, 255 }, { 0, 0, 0 } }); - - - std::cout << "Test specified ranges" << std::endl; - //verify that we can specify custom above and below range colors - table.SetAboveRangeColor(vtkm::Vec{ 1.0f, 0.0f, 0.0f }); //red - table.SetBelowRangeColor(vtkm::Vec{ 0.0f, 0.0f, 1.0f }); //green - const bool ran2 = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran2, "color table failed to execute"); - CheckColors(colors, { { 0, 0, 255 }, { 0, 255, 0 }, { 255, 0, 255 }, { 255, 0, 0 } }); - } - - static void TestRescaleRange() - { - std::cout << "Test Rescale Range" << std::endl; - vtkm::Range range{ -100.0, 100.0 }; - - //implement a blue2yellow color table - vtkm::Vec rgb1{ 0.0f, 0.0f, 1.0f }; - vtkm::Vec rgb2{ 1.0f, 1.0f, 0.0f }; - auto lab = vtkm::ColorSpace::Lab; - - vtkm::cont::ColorTable table(range, rgb1, rgb2, lab); - table.AddPoint(0.0, vtkm::Vec{ 0.5f, 0.5f, 0.5f }); - VTKM_TEST_ASSERT(table.GetRange() == range, "custom range not saved"); - - vtkm::cont::ColorTable newTable = table.MakeDeepCopy(); - VTKM_TEST_ASSERT(newTable.GetRange() == range, "custom range not saved"); - - vtkm::Range normalizedRange{ 0.0, 50.0 }; - newTable.RescaleToRange(normalizedRange); - VTKM_TEST_ASSERT(table.GetRange() == range, "deep copy not working properly"); - VTKM_TEST_ASSERT(newTable.GetRange() == normalizedRange, "rescale of range failed"); - VTKM_TEST_ASSERT(newTable.GetNumberOfPoints() == 3, - "rescaled has incorrect number of control points"); - - //Verify that the rescaled color table generates correct colors - auto field = vtkm::cont::make_ArrayHandle({ 0, 10, 20, 30, 40, 50 }); - - vtkm::cont::ArrayHandle colors; - const bool ran = vtkm::cont::ColorTableMap(field, newTable, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //values confirmed with ParaView 5.4 - CheckColors(colors, - { { 0, 0, 255 }, - { 105, 69, 204 }, - { 126, 109, 153 }, - { 156, 151, 117 }, - { 207, 202, 87 }, - { 255, 255, 0 } }); - } - - static void TestAddPoints() - { - std::cout << "Test Add Points" << std::endl; - - vtkm::Range range{ -20, 20.0 }; - auto rgbspace = vtkm::ColorSpace::RGB; - - vtkm::cont::ColorTable table(rgbspace); - table.AddPoint(-10.0, vtkm::Vec{ 0.0f, 1.0f, 1.0f }); - table.AddPoint(-20.0, vtkm::Vec{ 1.0f, 1.0f, 1.0f }); - table.AddPoint(20.0, vtkm::Vec{ 0.0f, 0.0f, 0.0f }); - table.AddPoint(0.0, vtkm::Vec{ 0.0f, 0.0f, 1.0f }); - - VTKM_TEST_ASSERT(table.GetRange() == range, "adding points to make range expand properly"); - VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 4, - "adding points caused number of control points to be wrong"); - - vtkm::cont::ArrayHandle colors; - auto field = vtkm::cont::make_ArrayHandle({ 10.0f, -5.0f, -15.0f }); - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - CheckColors(colors, { { 0, 0, 128 }, { 0, 128, 255 }, { 128, 255, 255 } }); - } - - static void TestAddSegments() - { - std::cout << "Test Add Segments" << std::endl; - - vtkm::Range range{ 0.0, 50.0 }; - auto diverging = vtkm::ColorSpace::Diverging; - - vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::CoolToWarm); - VTKM_TEST_ASSERT(table.GetColorSpace() == diverging, - "color space not switched when loading preset"); - - - //Opacity Ramp from 0 to 1 - table.AddSegmentAlpha(0.0, 0.0f, 1.0, 1.0f); - VTKM_TEST_ASSERT(table.GetNumberOfPointsAlpha() == 2, "incorrect number of alpha points"); - - table.RescaleToRange(range); - - //Verify that the opacity points have moved - vtkm::Vec opacityData; - table.GetPointAlpha(1, opacityData); - VTKM_TEST_ASSERT(test_equal(opacityData[0], range.Max), "rescale to range failed on opacity"); - VTKM_TEST_ASSERT(opacityData[1] == 1.0, "rescale changed opacity values"); - VTKM_TEST_ASSERT(opacityData[2] == 0.5, "rescale modified mid/sharp of opacity"); - VTKM_TEST_ASSERT(opacityData[3] == 0.0, "rescale modified mid/sharp of opacity"); - - - vtkm::cont::ArrayHandle colors; - auto field = vtkm::cont::make_ArrayHandle({ 0, 10, 20, 30, 40, 50 }); - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //values confirmed with ParaView 5.4 - CheckColors(colors, - { { 59, 76, 192, 0 }, - { 124, 159, 249, 51 }, - { 192, 212, 245, 102 }, - { 242, 203, 183, 153 }, - { 238, 133, 104, 204 }, - { 180, 4, 38, 255 } }); - } - - static void TestRemovePoints() - { - std::cout << "Test Remove Points" << std::endl; - - auto hsv = vtkm::ColorSpace::HSV; - - vtkm::cont::ColorTable table(hsv); - //implement Blue to Red Rainbow color table - table.AddSegment(0, - vtkm::Vec{ 0.0f, 0.0f, 1.0f }, - 1., //second points color should be replaced by following segment - vtkm::Vec{ 1.0f, 0.0f, 0.0f }); - - table.AddPoint(-10.0, vtkm::Vec{ 0.0f, 1.0f, 1.0f }); - table.AddPoint(-20.0, vtkm::Vec{ 1.0f, 1.0f, 1.0f }); - table.AddPoint(20.0, vtkm::Vec{ 1.0f, 0.0f, 0.0f }); - - VTKM_TEST_ASSERT(table.RemovePoint(-10.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePoint(-20.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePoint(20.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePoint(20.) == false, "can't remove a point that doesn't exist"); - - VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), - "removing points didn't update range"); - table.RescaleToRange(vtkm::Range{ 0.0, 50.0 }); - - vtkm::cont::ArrayHandle colors; - auto field = vtkm::cont::make_ArrayHandle({ 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f }); - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //values confirmed with ParaView 5.4 - CheckColors(colors, - { { 0, 0, 255 }, - { 0, 204, 255 }, - { 0, 255, 102 }, - { 102, 255, 0 }, - { 255, 204, 0 }, - { 255, 0, 0 } }); - - std::cout << " Change Color Space" << std::endl; - vtkm::cont::ArrayHandle colors_rgb; - table.SetColorSpace(vtkm::ColorSpace::RGB); - vtkm::cont::ColorTableMap(field, table, colors_rgb); - - CheckColors(colors_rgb, - { { 0, 0, 255 }, - { 51, 0, 204 }, - { 102, 0, 153 }, - { 153, 0, 102 }, - { 204, 0, 51 }, - { 255, 0, 0 } }); - } - - static void TestOpacityOnlyPoints() - { - std::cout << "Test Opacity Only Points" << std::endl; - - auto hsv = vtkm::ColorSpace::HSV; - - vtkm::cont::ColorTable table(hsv); - //implement only a color table - table.AddPointAlpha(0.0, 0.0f, 0.75f, 0.25f); - table.AddPointAlpha(1.0, 1.0f); - - table.AddPointAlpha(10.0, 0.5f, 0.5f, 0.0f); - table.AddPointAlpha(-10.0, 0.0f); - table.AddPointAlpha(-20.0, 1.0f); - table.AddPointAlpha(20.0, 0.5f); - - VTKM_TEST_ASSERT(table.RemovePointAlpha(10.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePointAlpha(-10.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePointAlpha(-20.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePointAlpha(20.) == true, "failed to remove a existing point"); - VTKM_TEST_ASSERT(table.RemovePointAlpha(20.) == false, - "can't remove a point that doesn't exist"); - - VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), - "removing points didn't update range"); - table.RescaleToRange(vtkm::Range{ 0.0, 50.0 }); - - vtkm::cont::ArrayHandle colors; - auto field = vtkm::cont::make_ArrayHandle({ 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f }); - const bool ran = vtkm::cont::ColorTableMap(field, table, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //values confirmed with ParaView 5.4 - CheckColors(colors, - { { 0, 0, 0, 0 }, - { 0, 0, 0, 1 }, - { 0, 0, 0, 11 }, - { 0, 0, 0, 52 }, - { 0, 0, 0, 203 }, - { 0, 0, 0, 255 } }); - } - - static void TestWorkletTransport() - { - std::cout << "Test Worklet Transport" << std::endl; - - using namespace vtkm::worklet::colorconversion; - - vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::Green); - VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), - "loading linear green table failed with wrong range"); - VTKM_TEST_ASSERT((table.GetNumberOfPoints() == 21), - "loading linear green table failed with number of control points"); - - auto samples = vtkm::cont::make_ArrayHandle({ 0.0, 0.5, 1.0 }); - - vtkm::cont::ArrayHandle colors; - vtkm::cont::Invoker invoke; - invoke(TransferFunction{}, samples, table, colors); - - CheckColors(colors, { { 14, 28, 31, 255 }, { 21, 150, 21, 255 }, { 255, 251, 230, 255 } }); - } - - static void TestSampling() - { - std::cout << "Test Sampling" << std::endl; - - vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::Green); - VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), - "loading linear green table failed with wrong range"); - VTKM_TEST_ASSERT((table.GetNumberOfPoints() == 21), - "loading linear green table failed with number of control points"); - - vtkm::cont::ArrayHandle colors; - constexpr vtkm::Id nvals = 3; - table.Sample(nvals, colors); - - CheckColors(colors, { { 14, 28, 31, 255 }, { 21, 150, 21, 255 }, { 255, 251, 230, 255 } }); - } - - static void TestLookupTable() - { - std::cout << "Test Lookup Table" << std::endl; - - //build a color table with clamping off and verify that sampling works - vtkm::Range range{ 0.0, 50.0 }; - vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::CoolToWarm); - table.RescaleToRange(range); - table.SetClampingOff(); - table.SetAboveRangeColor(vtkm::Vec{ 1.0f, 0.0f, 0.0f }); //red - table.SetBelowRangeColor(vtkm::Vec{ 0.0f, 0.0f, 1.0f }); //green - - vtkm::cont::ColorTableSamplesRGB samples; - table.Sample(256, samples); - VTKM_TEST_ASSERT((samples.Samples.GetNumberOfValues() == 260), "invalid sample length"); - - vtkm::cont::ArrayHandle colors; - auto field = vtkm::cont::make_ArrayHandle({ -1, 0, 10, 20, 30, 40, 50, 60 }); - const bool ran = vtkm::cont::ColorTableMap(field, samples, colors); - VTKM_TEST_ASSERT(ran, "color table failed to execute"); - - //values confirmed with ParaView 5.4 - CheckColors(colors, - { { 0, 0, 255 }, - { 59, 76, 192 }, - { 122, 157, 248 }, - { 191, 211, 246 }, - { 241, 204, 184 }, - { 238, 134, 105 }, - { 180, 4, 38 }, - { 255, 0, 0 } }); - } - - struct TestAll - { - VTKM_CONT void operator()() const - { - TestConstructors(); - TestLoadPresets(); - TestClamping(); - TestRangeColors(); - - TestRescaleRange(); //uses Lab - TestAddPoints(); //uses RGB - TestAddSegments(); //uses Diverging && opacity - TestRemovePoints(); //use HSV - - TestOpacityOnlyPoints(); - - TestWorkletTransport(); - TestSampling(); - TestLookupTable(); - } - }; - - static int Run(int argc, char* argv[]) - { - //We need to verify the color table runs on this specific device - //so we need to force our single device - vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(DeviceAdapterTag()); - return vtkm::cont::testing::Testing::Run(TestAll(), argc, argv); - } -}; -} -} -} -#endif diff --git a/vtkm/cont/testing/UnitTestColorTable.cxx b/vtkm/cont/testing/UnitTestColorTable.cxx new file mode 100644 index 000000000..e3c476d3e --- /dev/null +++ b/vtkm/cont/testing/UnitTestColorTable.cxx @@ -0,0 +1,505 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#include +#include +#include +#include +#include + +#include +#include + +namespace +{ + +template +void CheckColors(vtkm::cont::ArrayHandle> result, + const std::vector>& expected) +{ + using Vec = vtkm::Vec; + + VTKM_TEST_ASSERT(result.GetNumberOfValues() == static_cast(expected.size())); + auto portal = result.ReadPortal(); + for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index) + { + Vec resultValue = portal.Get(index); + Vec expectedValue = expected[static_cast(index)]; + VTKM_TEST_ASSERT( + resultValue == expectedValue, "Expected color ", expectedValue, " but got ", resultValue); + } +} + +void TestConstructors() +{ + vtkm::Range inValidRange{ 1.0, 0.0 }; + vtkm::Range range{ 0.0, 1.0 }; + vtkm::Vec rgb1{ 0.0f, 0.0f, 0.0f }; + vtkm::Vec rgb2{ 1.0f, 1.0f, 1.0f }; + auto rgbspace = vtkm::ColorSpace::RGB; + auto hsvspace = vtkm::ColorSpace::HSV; + auto diverging = vtkm::ColorSpace::Diverging; + + vtkm::cont::ColorTable table(rgbspace); + VTKM_TEST_ASSERT(table.GetColorSpace() == rgbspace, "color space not saved"); + VTKM_TEST_ASSERT(table.GetRange() == inValidRange, "default range incorrect"); + + vtkm::cont::ColorTable tableRGB(range, rgb1, rgb2, hsvspace); + VTKM_TEST_ASSERT(tableRGB.GetColorSpace() == hsvspace, "color space not saved"); + VTKM_TEST_ASSERT(tableRGB.GetRange() == range, "color range not saved"); + + vtkm::Vec rgba1{ 0.0f, 0.0f, 0.0f, 1.0f }; + vtkm::Vec rgba2{ 1.0f, 1.0f, 1.0f, 0.0f }; + vtkm::cont::ColorTable tableRGBA(range, rgba1, rgba2, diverging); + VTKM_TEST_ASSERT(tableRGBA.GetColorSpace() == diverging, "color space not saved"); + VTKM_TEST_ASSERT(tableRGBA.GetRange() == range, "color range not saved"); + + //verify we can store a vector of tables + std::vector tables; + tables.push_back(table); + tables.push_back(tableRGB); + tables.push_back(tableRGBA); + tables.push_back(tableRGBA); + tables.push_back(tableRGB); + tables.push_back(table); +} + +void TestLoadPresets() +{ + vtkm::Range range{ 0.0, 1.0 }; + auto rgbspace = vtkm::ColorSpace::RGB; + auto hsvspace = vtkm::ColorSpace::HSV; + auto labspace = vtkm::ColorSpace::Lab; + auto diverging = vtkm::ColorSpace::Diverging; + + { + vtkm::cont::ColorTable table(rgbspace); + VTKM_TEST_ASSERT(table.LoadPreset("Cool to Warm")); + VTKM_TEST_ASSERT(table.GetColorSpace() == diverging, + "color space not switched when loading preset"); + VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after loading preset"); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 3); + + VTKM_TEST_ASSERT(table.LoadPreset(vtkm::cont::ColorTable::Preset::CoolToWarmExtended)); + VTKM_TEST_ASSERT(table.GetColorSpace() == labspace, + "color space not switched when loading preset"); + VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after loading preset"); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 35); + + table.SetColorSpace(hsvspace); + VTKM_TEST_ASSERT((table.LoadPreset("no table with this name") == false), + "failed to error out on bad preset table name"); + //verify that after a failure we still have the previous preset loaded + VTKM_TEST_ASSERT(table.GetColorSpace() == hsvspace, + "color space not switched when loading preset"); + VTKM_TEST_ASSERT(table.GetRange() == range, "color range not correct after failing preset"); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 35); + } + + + //verify that we can get the presets + std::set names = vtkm::cont::ColorTable::GetPresets(); + VTKM_TEST_ASSERT(names.size() == 18, "incorrect number of names in preset set"); + + VTKM_TEST_ASSERT(names.count("Inferno") == 1, "names should contain inferno"); + VTKM_TEST_ASSERT(names.count("Black-Body Radiation") == 1, + "names should contain black-body radiation"); + VTKM_TEST_ASSERT(names.count("Viridis") == 1, "names should contain viridis"); + VTKM_TEST_ASSERT(names.count("Black - Blue - White") == 1, + "names should contain black, blue and white"); + VTKM_TEST_ASSERT(names.count("Blue to Orange") == 1, "names should contain samsel fire"); + VTKM_TEST_ASSERT(names.count("Jet") == 1, "names should contain jet"); + + // verify that we can load in all the listed color tables + for (auto&& name : names) + { + vtkm::cont::ColorTable table(name); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() > 0, "Issue loading preset ", name); + } + + auto presetEnum = { vtkm::cont::ColorTable::Preset::Default, + vtkm::cont::ColorTable::Preset::CoolToWarm, + vtkm::cont::ColorTable::Preset::CoolToWarmExtended, + vtkm::cont::ColorTable::Preset::Viridis, + vtkm::cont::ColorTable::Preset::Inferno, + vtkm::cont::ColorTable::Preset::Plasma, + vtkm::cont::ColorTable::Preset::BlackBodyRadiation, + vtkm::cont::ColorTable::Preset::XRay, + vtkm::cont::ColorTable::Preset::Green, + vtkm::cont::ColorTable::Preset::BlackBlueWhite, + vtkm::cont::ColorTable::Preset::BlueToOrange, + vtkm::cont::ColorTable::Preset::GrayToRed, + vtkm::cont::ColorTable::Preset::ColdAndHot, + vtkm::cont::ColorTable::Preset::BlueGreenOrange, + vtkm::cont::ColorTable::Preset::YellowGrayBlue, + vtkm::cont::ColorTable::Preset::RainbowUniform, + vtkm::cont::ColorTable::Preset::Jet, + vtkm::cont::ColorTable::Preset::RainbowDesaturated }; + for (vtkm::cont::ColorTable::Preset preset : presetEnum) + { + vtkm::cont::ColorTable table(preset); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() > 0, "Issue loading preset"); + } +} + +void TestClamping() +{ + std::cout << "Test Clamping" << std::endl; + + vtkm::Range range{ 0.0, 1.0 }; + vtkm::Vec rgb1{ 0.0f, 1.0f, 0.0f }; + vtkm::Vec rgb2{ 1.0f, 0.0f, 1.0f }; + auto rgbspace = vtkm::ColorSpace::RGB; + + vtkm::cont::ColorTable table(range, rgb1, rgb2, rgbspace); + VTKM_TEST_ASSERT(table.GetClamping() == true, "clamping not setup properly"); + + auto field = vtkm::cont::make_ArrayHandle({ -1, 0, 1, 2 }); + + vtkm::cont::ArrayHandle colors; + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //verify that we clamp the values to the expected range + CheckColors(colors, { { 0, 255, 0 }, { 0, 255, 0 }, { 255, 0, 255 }, { 255, 0, 255 } }); +} + +void TestRangeColors() +{ + std::cout << "Test default ranges" << std::endl; + + vtkm::Range range{ -1.0, 2.0 }; + vtkm::Vec rgb1{ 0.0f, 1.0f, 0.0f }; + vtkm::Vec rgb2{ 1.0f, 0.0f, 1.0f }; + auto rgbspace = vtkm::ColorSpace::RGB; + + vtkm::cont::ColorTable table(range, rgb1, rgb2, rgbspace); + table.SetClampingOff(); + VTKM_TEST_ASSERT(table.GetClamping() == false, "clamping not setup properly"); + + auto field = vtkm::cont::make_ArrayHandle({ -2, -1, 2, 3 }); + + vtkm::cont::ArrayHandle colors; + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //verify that both the above and below range colors are used, + //and that the default value of both is 0,0,0 + CheckColors(colors, { { 0, 0, 0 }, { 0, 255, 0 }, { 255, 0, 255 }, { 0, 0, 0 } }); + + + std::cout << "Test specified ranges" << std::endl; + //verify that we can specify custom above and below range colors + table.SetAboveRangeColor(vtkm::Vec{ 1.0f, 0.0f, 0.0f }); //red + table.SetBelowRangeColor(vtkm::Vec{ 0.0f, 0.0f, 1.0f }); //green + const bool ran2 = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran2, "color table failed to execute"); + CheckColors(colors, { { 0, 0, 255 }, { 0, 255, 0 }, { 255, 0, 255 }, { 255, 0, 0 } }); +} + +void TestRescaleRange() +{ + std::cout << "Test Rescale Range" << std::endl; + vtkm::Range range{ -100.0, 100.0 }; + + //implement a blue2yellow color table + vtkm::Vec rgb1{ 0.0f, 0.0f, 1.0f }; + vtkm::Vec rgb2{ 1.0f, 1.0f, 0.0f }; + auto lab = vtkm::ColorSpace::Lab; + + vtkm::cont::ColorTable table(range, rgb1, rgb2, lab); + table.AddPoint(0.0, vtkm::Vec{ 0.5f, 0.5f, 0.5f }); + VTKM_TEST_ASSERT(table.GetRange() == range, "custom range not saved"); + + vtkm::cont::ColorTable newTable = table.MakeDeepCopy(); + VTKM_TEST_ASSERT(newTable.GetRange() == range, "custom range not saved"); + + vtkm::Range normalizedRange{ 0.0, 50.0 }; + newTable.RescaleToRange(normalizedRange); + VTKM_TEST_ASSERT(table.GetRange() == range, "deep copy not working properly"); + VTKM_TEST_ASSERT(newTable.GetRange() == normalizedRange, "rescale of range failed"); + VTKM_TEST_ASSERT(newTable.GetNumberOfPoints() == 3, + "rescaled has incorrect number of control points"); + + //Verify that the rescaled color table generates correct colors + auto field = vtkm::cont::make_ArrayHandle({ 0, 10, 20, 30, 40, 50 }); + + vtkm::cont::ArrayHandle colors; + const bool ran = vtkm::cont::ColorTableMap(field, newTable, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //values confirmed with ParaView 5.4 + CheckColors(colors, + { { 0, 0, 255 }, + { 105, 69, 204 }, + { 126, 109, 153 }, + { 156, 151, 117 }, + { 207, 202, 87 }, + { 255, 255, 0 } }); +} + +void TestAddPoints() +{ + std::cout << "Test Add Points" << std::endl; + + vtkm::Range range{ -20, 20.0 }; + auto rgbspace = vtkm::ColorSpace::RGB; + + vtkm::cont::ColorTable table(rgbspace); + table.AddPoint(-10.0, vtkm::Vec{ 0.0f, 1.0f, 1.0f }); + table.AddPoint(-20.0, vtkm::Vec{ 1.0f, 1.0f, 1.0f }); + table.AddPoint(20.0, vtkm::Vec{ 0.0f, 0.0f, 0.0f }); + table.AddPoint(0.0, vtkm::Vec{ 0.0f, 0.0f, 1.0f }); + + VTKM_TEST_ASSERT(table.GetRange() == range, "adding points to make range expand properly"); + VTKM_TEST_ASSERT(table.GetNumberOfPoints() == 4, + "adding points caused number of control points to be wrong"); + + vtkm::cont::ArrayHandle colors; + auto field = vtkm::cont::make_ArrayHandle({ 10.0f, -5.0f, -15.0f }); + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + CheckColors(colors, { { 0, 0, 128 }, { 0, 128, 255 }, { 128, 255, 255 } }); +} + +void TestAddSegments() +{ + std::cout << "Test Add Segments" << std::endl; + + vtkm::Range range{ 0.0, 50.0 }; + auto diverging = vtkm::ColorSpace::Diverging; + + vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::CoolToWarm); + VTKM_TEST_ASSERT(table.GetColorSpace() == diverging, + "color space not switched when loading preset"); + + + //Opacity Ramp from 0 to 1 + table.AddSegmentAlpha(0.0, 0.0f, 1.0, 1.0f); + VTKM_TEST_ASSERT(table.GetNumberOfPointsAlpha() == 2, "incorrect number of alpha points"); + + table.RescaleToRange(range); + + //Verify that the opacity points have moved + vtkm::Vec opacityData; + table.GetPointAlpha(1, opacityData); + VTKM_TEST_ASSERT(test_equal(opacityData[0], range.Max), "rescale to range failed on opacity"); + VTKM_TEST_ASSERT(opacityData[1] == 1.0, "rescale changed opacity values"); + VTKM_TEST_ASSERT(opacityData[2] == 0.5, "rescale modified mid/sharp of opacity"); + VTKM_TEST_ASSERT(opacityData[3] == 0.0, "rescale modified mid/sharp of opacity"); + + + vtkm::cont::ArrayHandle colors; + auto field = vtkm::cont::make_ArrayHandle({ 0, 10, 20, 30, 40, 50 }); + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //values confirmed with ParaView 5.4 + CheckColors(colors, + { { 59, 76, 192, 0 }, + { 124, 159, 249, 51 }, + { 192, 212, 245, 102 }, + { 242, 203, 183, 153 }, + { 238, 133, 104, 204 }, + { 180, 4, 38, 255 } }); +} + +void TestRemovePoints() +{ + std::cout << "Test Remove Points" << std::endl; + + auto hsv = vtkm::ColorSpace::HSV; + + vtkm::cont::ColorTable table(hsv); + //implement Blue to Red Rainbow color table + table.AddSegment(0, + vtkm::Vec{ 0.0f, 0.0f, 1.0f }, + 1., //second points color should be replaced by following segment + vtkm::Vec{ 1.0f, 0.0f, 0.0f }); + + table.AddPoint(-10.0, vtkm::Vec{ 0.0f, 1.0f, 1.0f }); + table.AddPoint(-20.0, vtkm::Vec{ 1.0f, 1.0f, 1.0f }); + table.AddPoint(20.0, vtkm::Vec{ 1.0f, 0.0f, 0.0f }); + + VTKM_TEST_ASSERT(table.RemovePoint(-10.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePoint(-20.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePoint(20.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePoint(20.) == false, "can't remove a point that doesn't exist"); + + VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), + "removing points didn't update range"); + table.RescaleToRange(vtkm::Range{ 0.0, 50.0 }); + + vtkm::cont::ArrayHandle colors; + auto field = vtkm::cont::make_ArrayHandle({ 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f }); + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //values confirmed with ParaView 5.4 + CheckColors(colors, + { { 0, 0, 255 }, + { 0, 204, 255 }, + { 0, 255, 102 }, + { 102, 255, 0 }, + { 255, 204, 0 }, + { 255, 0, 0 } }); + + std::cout << " Change Color Space" << std::endl; + vtkm::cont::ArrayHandle colors_rgb; + table.SetColorSpace(vtkm::ColorSpace::RGB); + vtkm::cont::ColorTableMap(field, table, colors_rgb); + + CheckColors(colors_rgb, + { { 0, 0, 255 }, + { 51, 0, 204 }, + { 102, 0, 153 }, + { 153, 0, 102 }, + { 204, 0, 51 }, + { 255, 0, 0 } }); +} + +void TestOpacityOnlyPoints() +{ + std::cout << "Test Opacity Only Points" << std::endl; + + auto hsv = vtkm::ColorSpace::HSV; + + vtkm::cont::ColorTable table(hsv); + //implement only a color table + table.AddPointAlpha(0.0, 0.0f, 0.75f, 0.25f); + table.AddPointAlpha(1.0, 1.0f); + + table.AddPointAlpha(10.0, 0.5f, 0.5f, 0.0f); + table.AddPointAlpha(-10.0, 0.0f); + table.AddPointAlpha(-20.0, 1.0f); + table.AddPointAlpha(20.0, 0.5f); + + VTKM_TEST_ASSERT(table.RemovePointAlpha(10.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePointAlpha(-10.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePointAlpha(-20.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePointAlpha(20.) == true, "failed to remove a existing point"); + VTKM_TEST_ASSERT(table.RemovePointAlpha(20.) == false, "can't remove a point that doesn't exist"); + + VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), + "removing points didn't update range"); + table.RescaleToRange(vtkm::Range{ 0.0, 50.0 }); + + vtkm::cont::ArrayHandle colors; + auto field = vtkm::cont::make_ArrayHandle({ 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f }); + const bool ran = vtkm::cont::ColorTableMap(field, table, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //values confirmed with ParaView 5.4 + CheckColors(colors, + { { 0, 0, 0, 0 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 11 }, + { 0, 0, 0, 52 }, + { 0, 0, 0, 203 }, + { 0, 0, 0, 255 } }); +} + +void TestWorkletTransport() +{ + std::cout << "Test Worklet Transport" << std::endl; + + using namespace vtkm::worklet::colorconversion; + + vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::Green); + VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), + "loading linear green table failed with wrong range"); + VTKM_TEST_ASSERT((table.GetNumberOfPoints() == 21), + "loading linear green table failed with number of control points"); + + auto samples = vtkm::cont::make_ArrayHandle({ 0.0, 0.5, 1.0 }); + + vtkm::cont::ArrayHandle colors; + vtkm::cont::Invoker invoke; + invoke(TransferFunction{}, samples, table, colors); + + CheckColors(colors, { { 14, 28, 31, 255 }, { 21, 150, 21, 255 }, { 255, 251, 230, 255 } }); +} + +void TestSampling() +{ + std::cout << "Test Sampling" << std::endl; + + vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::Green); + VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }), + "loading linear green table failed with wrong range"); + VTKM_TEST_ASSERT((table.GetNumberOfPoints() == 21), + "loading linear green table failed with number of control points"); + + vtkm::cont::ArrayHandle colors; + constexpr vtkm::Id nvals = 3; + table.Sample(nvals, colors); + + CheckColors(colors, { { 14, 28, 31, 255 }, { 21, 150, 21, 255 }, { 255, 251, 230, 255 } }); +} + +void TestLookupTable() +{ + std::cout << "Test Lookup Table" << std::endl; + + //build a color table with clamping off and verify that sampling works + vtkm::Range range{ 0.0, 50.0 }; + vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::CoolToWarm); + table.RescaleToRange(range); + table.SetClampingOff(); + table.SetAboveRangeColor(vtkm::Vec{ 1.0f, 0.0f, 0.0f }); //red + table.SetBelowRangeColor(vtkm::Vec{ 0.0f, 0.0f, 1.0f }); //green + + vtkm::cont::ColorTableSamplesRGB samples; + table.Sample(256, samples); + VTKM_TEST_ASSERT((samples.Samples.GetNumberOfValues() == 260), "invalid sample length"); + + vtkm::cont::ArrayHandle colors; + auto field = vtkm::cont::make_ArrayHandle({ -1, 0, 10, 20, 30, 40, 50, 60 }); + const bool ran = vtkm::cont::ColorTableMap(field, samples, colors); + VTKM_TEST_ASSERT(ran, "color table failed to execute"); + + //values confirmed with ParaView 5.4 + CheckColors(colors, + { { 0, 0, 255 }, + { 59, 76, 192 }, + { 122, 157, 248 }, + { 191, 211, 246 }, + { 241, 204, 184 }, + { 238, 134, 105 }, + { 180, 4, 38 }, + { 255, 0, 0 } }); +} + +void Run() +{ + TestConstructors(); + TestLoadPresets(); + TestClamping(); + TestRangeColors(); + + TestRescaleRange(); //uses Lab + TestAddPoints(); //uses RGB + TestAddSegments(); //uses Diverging && opacity + TestRemovePoints(); //use HSV + + TestOpacityOnlyPoints(); + + TestWorkletTransport(); + TestSampling(); + TestLookupTable(); +} + +} // anonymous namespace + +int UnitTestColorTable(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(Run, argc, argv); +}