diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c258e04..20577b0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s - Added a `vtk` extract that saves each mesh domain to a legacy vtk file grouped, with all domain data grouped by a `.visit` file. - Added WarpX Streamline filter that uses charged particles. - Added seed population options for particle advection: point, point list, line, and box +- Added a `cylinder` option to the clip filter. ### Changed - Changed the Data Binning filter to accept a `reduction_field` parameter (instead of `var`), and similarly the axis parameters to take `field` (instead of `var`). The `var` style parameters are still accepted, but deprecated and will be removed in a future release. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 95728c67b..3f8816180 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,11 +22,11 @@ ######################## variables: - ubuntu_20_04_tag: alpinedav/ascent-devel:ubuntu-20.04-x86_64-tpls_2024-04-29-sha3234b3 - ubuntu_22_04_tag: alpinedav/ascent-devel:ubuntu-22.04-x86_64-tpls_2024-04-29-sha3234b3 - ubuntu_20_04_cuda_11_4_3_tag: alpinedav/ascent-devel:ubuntu-20.04-cuda-11.4.3-x86_64-tpls_2024-04-30-shad5b6a9 - ubuntu_20_04_cuda_12_1_1_tag: alpinedav/ascent-devel:ubuntu-20.04-cuda-12.1.1-x86_64-tpls_2024-04-30-shad5b6a9 - ubuntu_20_04_rocm_6_0_0_tag: alpinedav/ascent-devel:ubuntu-20.04-rocm-6.0.0--x86_64-build-ascent-tpls_2024-04-19-shaee18b8 + ubuntu_20_04_tag: alpinedav/ascent-devel:ubuntu-20.04-x86_64-tpls_2024-05-03-sha29a328 + ubuntu_22_04_tag: alpinedav/ascent-devel:ubuntu-22.04-x86_64-tpls_2024-05-09-shaa5bd0a + ubuntu_20_04_cuda_11_4_3_tag: alpinedav/ascent-devel:ubuntu-20.04-cuda-11.4.3-x86_64-tpls_2024-05-10-shaa5bd0a + ubuntu_20_04_cuda_12_1_1_tag: alpinedav/ascent-devel:ubuntu-20.04-cuda-12.1.1-x86_64-tpls_2024-05-10-shaa5bd0a + ubuntu_20_04_rocm_6_0_0_tag: alpinedav/ascent-devel:ubuntu-20.04-rocm-6.0.0--x86_64-build-ascent-tpls_2024-05-09-shaa5bd0a # only build merge target pr to develop diff --git a/scripts/build_ascent/2024_05_03_vtkm-mr3215-ext-geom-fix.patch b/scripts/build_ascent/2024_05_03_vtkm-mr3215-ext-geom-fix.patch new file mode 100644 index 000000000..ed82e5630 --- /dev/null +++ b/scripts/build_ascent/2024_05_03_vtkm-mr3215-ext-geom-fix.patch @@ -0,0 +1,145 @@ +From 49518e5054c607942f644c82a5289e12b0f50476 Mon Sep 17 00:00:00 2001 +From: Kenneth Moreland +Date: Fri, 3 May 2024 09:22:56 -0400 +Subject: [PATCH] Fix bug with ExtractGeometry filter + +The `ExtractGeometry` filter was outputing datasets containing +`CellSetPermutation` as the representation for the cells. Although this is +technically correct and a very fast implementation, it is essentially +useless. The problem is that any downstream processing will have to know +that the data has a `CellSetPermutation`. None do (because the permutation +can be on any other cell set type, which creates an explosion of possible +cell types). + +Like was done with `Threshold` a while ago, this problem is fixed by deep +copying the result into a `CellSetExplicit`. This behavior is consistent +with VTK. +--- + .../changelog/extract-geometry-permutation.md | 13 +++++++ + .../testing/UnitTestExtractGeometryFilter.cxx | 13 ++++++- + .../worklet/ExtractGeometry.h | 34 +++++++------------ + 3 files changed, 37 insertions(+), 23 deletions(-) + create mode 100644 docs/changelog/extract-geometry-permutation.md + +diff --git a/docs/changelog/extract-geometry-permutation.md b/docs/changelog/extract-geometry-permutation.md +new file mode 100644 +index 0000000000..8a90495f76 +--- /dev/null ++++ b/docs/changelog/extract-geometry-permutation.md +@@ -0,0 +1,13 @@ ++# Fix bug with ExtractGeometry filter ++ ++The `ExtractGeometry` filter was outputing datasets containing ++`CellSetPermutation` as the representation for the cells. Although this is ++technically correct and a very fast implementation, it is essentially ++useless. The problem is that any downstream processing will have to know ++that the data has a `CellSetPermutation`. None do (because the permutation ++can be on any other cell set type, which creates an explosion of possible ++cell types). ++ ++Like was done with `Threshold` a while ago, this problem is fixed by deep ++copying the result into a `CellSetExplicit`. This behavior is consistent ++with VTK. +diff --git a/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx b/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx +index 675df8f77c..14de333666 100644 +--- a/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx ++++ b/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx +@@ -11,6 +11,7 @@ + #include + #include + ++#include + #include + + using vtkm::cont::testing::MakeTestDataSet; +@@ -41,11 +42,21 @@ public: + vtkm::cont::DataSet output = extractGeometry.Execute(dataset); + VTKM_TEST_ASSERT(test_equal(output.GetNumberOfCells(), 8), "Wrong result for ExtractGeometry"); + ++ vtkm::filter::clean_grid::CleanGrid cleanGrid; ++ cleanGrid.SetCompactPointFields(true); ++ cleanGrid.SetMergePoints(false); ++ vtkm::cont::DataSet cleanOutput = cleanGrid.Execute(output); ++ + vtkm::cont::ArrayHandle outCellData; +- output.GetField("cellvar").GetData().AsArrayHandle(outCellData); ++ cleanOutput.GetField("cellvar").GetData().AsArrayHandle(outCellData); + + VTKM_TEST_ASSERT(outCellData.ReadPortal().Get(0) == 21.f, "Wrong cell field data"); + VTKM_TEST_ASSERT(outCellData.ReadPortal().Get(7) == 42.f, "Wrong cell field data"); ++ ++ vtkm::cont::ArrayHandle outPointData; ++ cleanOutput.GetField("pointvar").GetData().AsArrayHandle(outPointData); ++ VTKM_TEST_ASSERT(outPointData.ReadPortal().Get(0) == 99); ++ VTKM_TEST_ASSERT(outPointData.ReadPortal().Get(7) == 90); + } + + static void TestUniformByBox1() +diff --git a/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h b/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h +index 97521335f2..449d7eae60 100644 +--- a/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h ++++ b/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h +@@ -10,11 +10,13 @@ + #ifndef vtkm_m_worklet_ExtractGeometry_h + #define vtkm_m_worklet_ExtractGeometry_h + ++#include + #include + + #include + #include + #include ++#include + #include + #include + #include +@@ -114,28 +116,13 @@ public: + } + }; + +- //////////////////////////////////////////////////////////////////////////////////// +- // Extract cells by ids permutes input data +- template +- vtkm::cont::CellSetPermutation Run(const CellSetType& cellSet, +- const vtkm::cont::ArrayHandle& cellIds) +- { +- using OutputType = vtkm::cont::CellSetPermutation; +- +- vtkm::cont::ArrayCopy(cellIds, this->ValidCellIds); +- +- return OutputType(this->ValidCellIds, cellSet); +- } +- +- //////////////////////////////////////////////////////////////////////////////////// +- // Extract cells by implicit function permutes input data + template +- vtkm::cont::CellSetPermutation Run(const CellSetType& cellSet, +- const vtkm::cont::CoordinateSystem& coordinates, +- const ImplicitFunction& implicitFunction, +- bool extractInside, +- bool extractBoundaryCells, +- bool extractOnlyBoundaryCells) ++ vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet, ++ const vtkm::cont::CoordinateSystem& coordinates, ++ const ImplicitFunction& implicitFunction, ++ bool extractInside, ++ bool extractBoundaryCells, ++ bool extractOnlyBoundaryCells) + { + // Worklet output will be a boolean passFlag array + vtkm::cont::ArrayHandle passFlags; +@@ -149,7 +136,10 @@ public: + vtkm::cont::Algorithm::CopyIf(indices, passFlags, this->ValidCellIds); + + // generate the cellset +- return vtkm::cont::CellSetPermutation(this->ValidCellIds, cellSet); ++ vtkm::cont::CellSetPermutation permutedCellSet(this->ValidCellIds, cellSet); ++ ++ vtkm::cont::CellSetExplicit<> outputCells; ++ return vtkm::worklet::CellDeepCopy::Run(permutedCellSet); + } + + vtkm::cont::ArrayHandle GetValidCellIds() const { return this->ValidCellIds; } +-- +GitLab + diff --git a/scripts/build_ascent/build_ascent.sh b/scripts/build_ascent/build_ascent.sh index adc9cb9d5..39f65cdd5 100755 --- a/scripts/build_ascent/build_ascent.sh +++ b/scripts/build_ascent/build_ascent.sh @@ -363,6 +363,7 @@ if [ ! -d ${vtkm_src_dir} ]; then # apply vtk-m patch cd ${vtkm_src_dir} patch -p1 < ${script_dir}/2023_12_06_vtkm-mr3160-rocthrust-fix.patch + patch -p1 < ${script_dir}/2024_05_03_vtkm-mr3215-ext-geom-fix.patch cd ${root_dir} fi diff --git a/scripts/uberenv_configs/packages/vtk-m/2024_05_03_vtkm-mr3215-ext-geom-fix.patch b/scripts/uberenv_configs/packages/vtk-m/2024_05_03_vtkm-mr3215-ext-geom-fix.patch new file mode 100644 index 000000000..ed82e5630 --- /dev/null +++ b/scripts/uberenv_configs/packages/vtk-m/2024_05_03_vtkm-mr3215-ext-geom-fix.patch @@ -0,0 +1,145 @@ +From 49518e5054c607942f644c82a5289e12b0f50476 Mon Sep 17 00:00:00 2001 +From: Kenneth Moreland +Date: Fri, 3 May 2024 09:22:56 -0400 +Subject: [PATCH] Fix bug with ExtractGeometry filter + +The `ExtractGeometry` filter was outputing datasets containing +`CellSetPermutation` as the representation for the cells. Although this is +technically correct and a very fast implementation, it is essentially +useless. The problem is that any downstream processing will have to know +that the data has a `CellSetPermutation`. None do (because the permutation +can be on any other cell set type, which creates an explosion of possible +cell types). + +Like was done with `Threshold` a while ago, this problem is fixed by deep +copying the result into a `CellSetExplicit`. This behavior is consistent +with VTK. +--- + .../changelog/extract-geometry-permutation.md | 13 +++++++ + .../testing/UnitTestExtractGeometryFilter.cxx | 13 ++++++- + .../worklet/ExtractGeometry.h | 34 +++++++------------ + 3 files changed, 37 insertions(+), 23 deletions(-) + create mode 100644 docs/changelog/extract-geometry-permutation.md + +diff --git a/docs/changelog/extract-geometry-permutation.md b/docs/changelog/extract-geometry-permutation.md +new file mode 100644 +index 0000000000..8a90495f76 +--- /dev/null ++++ b/docs/changelog/extract-geometry-permutation.md +@@ -0,0 +1,13 @@ ++# Fix bug with ExtractGeometry filter ++ ++The `ExtractGeometry` filter was outputing datasets containing ++`CellSetPermutation` as the representation for the cells. Although this is ++technically correct and a very fast implementation, it is essentially ++useless. The problem is that any downstream processing will have to know ++that the data has a `CellSetPermutation`. None do (because the permutation ++can be on any other cell set type, which creates an explosion of possible ++cell types). ++ ++Like was done with `Threshold` a while ago, this problem is fixed by deep ++copying the result into a `CellSetExplicit`. This behavior is consistent ++with VTK. +diff --git a/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx b/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx +index 675df8f77c..14de333666 100644 +--- a/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx ++++ b/vtkm/filter/entity_extraction/testing/UnitTestExtractGeometryFilter.cxx +@@ -11,6 +11,7 @@ + #include + #include + ++#include + #include + + using vtkm::cont::testing::MakeTestDataSet; +@@ -41,11 +42,21 @@ public: + vtkm::cont::DataSet output = extractGeometry.Execute(dataset); + VTKM_TEST_ASSERT(test_equal(output.GetNumberOfCells(), 8), "Wrong result for ExtractGeometry"); + ++ vtkm::filter::clean_grid::CleanGrid cleanGrid; ++ cleanGrid.SetCompactPointFields(true); ++ cleanGrid.SetMergePoints(false); ++ vtkm::cont::DataSet cleanOutput = cleanGrid.Execute(output); ++ + vtkm::cont::ArrayHandle outCellData; +- output.GetField("cellvar").GetData().AsArrayHandle(outCellData); ++ cleanOutput.GetField("cellvar").GetData().AsArrayHandle(outCellData); + + VTKM_TEST_ASSERT(outCellData.ReadPortal().Get(0) == 21.f, "Wrong cell field data"); + VTKM_TEST_ASSERT(outCellData.ReadPortal().Get(7) == 42.f, "Wrong cell field data"); ++ ++ vtkm::cont::ArrayHandle outPointData; ++ cleanOutput.GetField("pointvar").GetData().AsArrayHandle(outPointData); ++ VTKM_TEST_ASSERT(outPointData.ReadPortal().Get(0) == 99); ++ VTKM_TEST_ASSERT(outPointData.ReadPortal().Get(7) == 90); + } + + static void TestUniformByBox1() +diff --git a/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h b/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h +index 97521335f2..449d7eae60 100644 +--- a/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h ++++ b/vtkm/filter/entity_extraction/worklet/ExtractGeometry.h +@@ -10,11 +10,13 @@ + #ifndef vtkm_m_worklet_ExtractGeometry_h + #define vtkm_m_worklet_ExtractGeometry_h + ++#include + #include + + #include + #include + #include ++#include + #include + #include + #include +@@ -114,28 +116,13 @@ public: + } + }; + +- //////////////////////////////////////////////////////////////////////////////////// +- // Extract cells by ids permutes input data +- template +- vtkm::cont::CellSetPermutation Run(const CellSetType& cellSet, +- const vtkm::cont::ArrayHandle& cellIds) +- { +- using OutputType = vtkm::cont::CellSetPermutation; +- +- vtkm::cont::ArrayCopy(cellIds, this->ValidCellIds); +- +- return OutputType(this->ValidCellIds, cellSet); +- } +- +- //////////////////////////////////////////////////////////////////////////////////// +- // Extract cells by implicit function permutes input data + template +- vtkm::cont::CellSetPermutation Run(const CellSetType& cellSet, +- const vtkm::cont::CoordinateSystem& coordinates, +- const ImplicitFunction& implicitFunction, +- bool extractInside, +- bool extractBoundaryCells, +- bool extractOnlyBoundaryCells) ++ vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet, ++ const vtkm::cont::CoordinateSystem& coordinates, ++ const ImplicitFunction& implicitFunction, ++ bool extractInside, ++ bool extractBoundaryCells, ++ bool extractOnlyBoundaryCells) + { + // Worklet output will be a boolean passFlag array + vtkm::cont::ArrayHandle passFlags; +@@ -149,7 +136,10 @@ public: + vtkm::cont::Algorithm::CopyIf(indices, passFlags, this->ValidCellIds); + + // generate the cellset +- return vtkm::cont::CellSetPermutation(this->ValidCellIds, cellSet); ++ vtkm::cont::CellSetPermutation permutedCellSet(this->ValidCellIds, cellSet); ++ ++ vtkm::cont::CellSetExplicit<> outputCells; ++ return vtkm::worklet::CellDeepCopy::Run(permutedCellSet); + } + + vtkm::cont::ArrayHandle GetValidCellIds() const { return this->ValidCellIds; } +-- +GitLab + diff --git a/scripts/uberenv_configs/packages/vtk-m/package.py b/scripts/uberenv_configs/packages/vtk-m/package.py index 1704b928f..be1039c20 100644 --- a/scripts/uberenv_configs/packages/vtk-m/package.py +++ b/scripts/uberenv_configs/packages/vtk-m/package.py @@ -152,6 +152,10 @@ class VtkM(CMakePackage, CudaPackage, ROCmPackage): # Patch patch("diy-include-cstddef.patch", when="@1.5.3:1.8.0") + # VTK-m PR #3215 + # https://gitlab.kitware.com/vtk/vtk-m/-/merge_requests/3215 + patch("2024_05_03_vtkm-mr3215-ext-geom-fix.patch", when="@2.1:") + # VTK-M PR#2972 # https://gitlab.kitware.com/vtk/vtk-m/-/merge_requests/2972 patch("vtkm-cuda-swap-conflict-pr2972.patch", when="@1.9 +cuda ^cuda@12:") diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp index 81cd64eb3..cf45984a5 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp @@ -666,7 +666,7 @@ VTKHCleanGrid::execute() throw_error); if(topo_name == "") { - // this creates a data object with an invalid soource + // this creates a data object with an invalid source set_output(new DataObject()); return; } @@ -1219,16 +1219,157 @@ VTKHThreshold::verify_params(const conduit::Node ¶ms, conduit::Node &info) { info.reset(); + bool res = true; - bool res = check_string("field",params, info, true); + bool type_present = false; - res = check_numeric("min_value",params, info, true, true) && res; - res = check_numeric("max_value",params, info, true, true) && res; + if(params.has_child("field")) + { + type_present = true; + } + else if(params.has_child("sphere")) + { + type_present = true; + } + else if(params.has_child("cylinder")) + { + type_present = true; + } + else if(params.has_child("box")) + { + type_present = true; + } + else if(params.has_child("plane")) + { + type_present = true; + } + else if(params.has_child("multi_plane")) + { + type_present = true; + } + + if(!type_present) + { + info["errors"].append() = "Missing required parameter. Threshold must specify 'field', 'sphere', 'cylinder', 'box', or 'plane'"; + res = false; + } + else + { + if(params.has_child("sphere")) + { + res = check_numeric("sphere/center/x",params, info, true, true) && res; + res = check_numeric("sphere/center/y",params, info, true, true) && res; + res = check_numeric("sphere/center/z",params, info, true, true) && res; + res = check_numeric("sphere/radius",params, info, true, true) && res; + } + else if(params.has_child("cylinder")) + { + res = check_numeric("cylinder/center/x",params, info, true, true) && res; + res = check_numeric("cylinder/center/y",params, info, true, true) && res; + res = check_numeric("cylinder/center/z",params, info, true, true) && res; + res = check_numeric("cylinder/axis/x",params, info, true, true) && res; + res = check_numeric("cylinder/axis/y",params, info, true, true) && res; + res = check_numeric("cylinder/axis/z",params, info, true, true) && res; + res = check_numeric("cylinder/radius",params, info, true, true) && res; + } + else if(params.has_child("box")) + { + res = check_numeric("box/min/x",params, info, true, true) && res; + res = check_numeric("box/min/y",params, info, true, true) && res; + res = check_numeric("box/min/z",params, info, true, true) && res; + res = check_numeric("box/max/x",params, info, true, true) && res; + res = check_numeric("box/max/y",params, info, true, true) && res; + res = check_numeric("box/max/z",params, info, true, true) && res; + } + else if(params.has_child("plane")) + { + res = check_numeric("plane/point/x",params, info, true, true) && res; + res = check_numeric("plane/point/y",params, info, true, true) && res; + res = check_numeric("plane/point/z",params, info, true, true) && res; + res = check_numeric("plane/normal/x",params, info, true, true) && res; + res = check_numeric("plane/normal/y",params, info, true, true) && res; + res = check_numeric("plane/normal/z",params, info, true, true) && res; + } + else if(params.has_child("multi_plane")) + { + res = check_numeric("multi_plane/point1/x",params, info, true, true) && res; + res = check_numeric("multi_plane/point1/y",params, info, true, true) && res; + res = check_numeric("multi_plane/point1/z",params, info, true, true) && res; + res = check_numeric("multi_plane/normal1/x",params, info, true, true) && res; + res = check_numeric("multi_plane/normal1/y",params, info, true, true) && res; + res = check_numeric("multi_plane/normal1/z",params, info, true, true) && res; + + res = check_numeric("multi_plane/point2/x",params, info, true, true) && res; + res = check_numeric("multi_plane/point2/y",params, info, true, true) && res; + res = check_numeric("multi_plane/point2/z",params, info, true, true) && res; + res = check_numeric("multi_plane/normal2/x",params, info, true, true) && res; + res = check_numeric("multi_plane/normal2/y",params, info, true, true) && res; + res = check_numeric("multi_plane/normal2/z",params, info, true, true) && res; + } + } + + // we either need 'field` or `topology` + if(!params.has_child("field")) + { + res &= check_string("topology",params, info, false); + } + + // field case + res = check_string("field",params, info, false); + res = check_numeric("min_value",params, info, false, true) && res; + res = check_numeric("max_value",params, info, false, true) && res; + + res = check_string("invert",params, info, false) && res; std::vector valid_paths; + valid_paths.push_back("invert"); valid_paths.push_back("field"); valid_paths.push_back("min_value"); valid_paths.push_back("max_value"); + + valid_paths.push_back("topology"); + valid_paths.push_back("extract"); + + valid_paths.push_back("sphere/center/x"); + valid_paths.push_back("sphere/center/y"); + valid_paths.push_back("sphere/center/z"); + valid_paths.push_back("sphere/radius"); + + valid_paths.push_back("cylinder/center/x"); + valid_paths.push_back("cylinder/center/y"); + valid_paths.push_back("cylinder/center/z"); + valid_paths.push_back("cylinder/axis/x"); + valid_paths.push_back("cylinder/axis/y"); + valid_paths.push_back("cylinder/axis/z"); + valid_paths.push_back("cylinder/radius"); + + valid_paths.push_back("box/min/x"); + valid_paths.push_back("box/min/y"); + valid_paths.push_back("box/min/z"); + valid_paths.push_back("box/max/x"); + valid_paths.push_back("box/max/y"); + valid_paths.push_back("box/max/z"); + + valid_paths.push_back("plane/point/x"); + valid_paths.push_back("plane/point/y"); + valid_paths.push_back("plane/point/z"); + valid_paths.push_back("plane/normal/x"); + valid_paths.push_back("plane/normal/y"); + valid_paths.push_back("plane/normal/z"); + + valid_paths.push_back("multi_plane/point1/x"); + valid_paths.push_back("multi_plane/point1/y"); + valid_paths.push_back("multi_plane/point1/z"); + valid_paths.push_back("multi_plane/normal1/x"); + valid_paths.push_back("multi_plane/normal1/y"); + valid_paths.push_back("multi_plane/normal1/z"); + + valid_paths.push_back("multi_plane/point2/x"); + valid_paths.push_back("multi_plane/point2/y"); + valid_paths.push_back("multi_plane/point2/z"); + valid_paths.push_back("multi_plane/normal2/x"); + valid_paths.push_back("multi_plane/normal2/y"); + valid_paths.push_back("multi_plane/normal2/z"); std::string surprises = surprise_check(valid_paths, params); if(surprises != "") @@ -1257,38 +1398,149 @@ VTKHThreshold::execute() set_output(data_object); return; } + std::shared_ptr collection = data_object->as_vtkh_collection(); - std::string field_name = params()["field"].as_string(); - if(!collection->has_field(field_name)) + // find right topology, either via field name or topology param + std::string topo_name = ""; + + if(params().has_child("field")) { - bool throw_error = false; - detail::field_error(field_name, this->name(), collection, throw_error); - // this creates a data object with an invalid soource - set_output(new DataObject()); - return; - } + std::string field_name = params()["field"].as_string(); + if(!collection->has_field(field_name)) + { + bool throw_error = false; + detail::field_error(field_name, this->name(), collection, throw_error); + // this creates a data object with an invalid source + set_output(new DataObject()); + return; + } - std::string topo_name = collection->field_topology(field_name); + topo_name = collection->field_topology(field_name); + + } + else + { + bool throw_error = false; + topo_name = detail::resolve_topology(params(), + this->name(), + collection, + throw_error); + if(topo_name == "") + { + // this creates a data object with an invalid source + set_output(new DataObject()); + return; + } + } vtkh::DataSet &data = collection->dataset_by_topology(topo_name); vtkh::Threshold thresher; - thresher.SetInput(&data); - thresher.SetField(field_name); - const Node &n_min_val = params()["min_value"]; - const Node &n_max_val = params()["max_value"]; + if(params().has_child("invert")) + { + std::string invert = params()["invert"].as_string(); + if(invert == "true") + { + thresher.SetInvertThreshold(true); + } + } - // convert to contig doubles - double min_val = get_float64(n_min_val, data_object); - double max_val = get_float64(n_max_val, data_object); - thresher.SetUpperThreshold(max_val); - thresher.SetLowerThreshold(min_val); + // field case + if(params().has_child("field")) + { + std::string field_name = params()["field"].as_string(); + thresher.SetField(field_name); - thresher.Update(); + const Node &n_min_val = params()["min_value"]; + const Node &n_max_val = params()["max_value"]; + // convert to contig doubles + double min_val = get_float64(n_min_val, data_object); + double max_val = get_float64(n_max_val, data_object); + thresher.SetFieldUpperThreshold(max_val); + thresher.SetFieldLowerThreshold(min_val); + } + else // spatial select cases + { + if(params().has_path("sphere")) + { + const Node &sphere = params()["sphere"]; + double center[3]; + + center[0] = get_float64(sphere["center/x"], data_object); + center[1] = get_float64(sphere["center/y"], data_object); + center[2] = get_float64(sphere["center/z"], data_object); + double radius = get_float64(sphere["radius"], data_object); + thresher.SetSphereThreshold(center, radius); + } + else if(params().has_path("cylinder")) + { + const Node &cylinder = params()["cylinder"]; + double center[3]; + double axis[3]; + + center[0] = get_float64(cylinder["center/x"], data_object); + center[1] = get_float64(cylinder["center/y"], data_object); + center[2] = get_float64(cylinder["center/z"], data_object); + + axis[0] = get_float64(cylinder["axis/x"], data_object); + axis[1] = get_float64(cylinder["axis/y"], data_object); + axis[2] = get_float64(cylinder["axis/z"], data_object); + + double radius = get_float64(cylinder["radius"], data_object); + thresher.SetCylinderThreshold(center, axis, radius); + } + else if(params().has_path("box")) + { + const Node &box = params()["box"]; + vtkm::Bounds bounds; + bounds.X.Min= get_float64(box["min/x"], data_object); + bounds.Y.Min= get_float64(box["min/y"], data_object); + bounds.Z.Min= get_float64(box["min/z"], data_object); + bounds.X.Max = get_float64(box["max/x"], data_object); + bounds.Y.Max = get_float64(box["max/y"], data_object); + bounds.Z.Max = get_float64(box["max/z"], data_object); + thresher.SetBoxThreshold(bounds); + } + else if(params().has_path("plane")) + { + const Node &plane= params()["plane"]; + double point[3], normal[3];; + + point[0] = get_float64(plane["point/x"], data_object); + point[1] = get_float64(plane["point/y"], data_object); + point[2] = get_float64(plane["point/z"], data_object); + normal[0] = get_float64(plane["normal/x"], data_object); + normal[1] = get_float64(plane["normal/y"], data_object); + normal[2] = get_float64(plane["normal/z"], data_object); + thresher.SetPlaneThreshold(point, normal); + } + // else if(params().has_path("multi_plane")) + // { + // const Node &plane= params()["multi_plane"]; + // double point1[3], normal1[3], point2[3], normal2[3]; + // + // point1[0] = get_float64(plane["point1/x"], data_object); + // point1[1] = get_float64(plane["point1/y"], data_object); + // point1[2] = get_float64(plane["point1/z"], data_object); + // normal1[0] = get_float64(plane["normal1/x"], data_object); + // normal1[1] = get_float64(plane["normal1/y"], data_object); + // normal1[2] = get_float64(plane["normal1/z"], data_object); + // point2[0] = get_float64(plane["point2/x"], data_object); + // point2[1] = get_float64(plane["point2/y"], data_object); + // point2[2] = get_float64(plane["point2/z"], data_object); + // normal2[0] = get_float64(plane["normal2/x"], data_object); + // normal2[1] = get_float64(plane["normal2/y"], data_object); + // normal2[2] = get_float64(plane["normal2/z"], data_object); + // clipper.Set2PlaneClip(point1, normal1, point2, normal2); + // } + + } + + thresher.Update(); vtkh::DataSet *thresh_output = thresher.GetOutput(); // we need to pass through the rest of the topologies, untouched, @@ -1337,6 +1589,10 @@ VTKHClip::verify_params(const conduit::Node ¶ms, { type_present = true; } + else if(params.has_child("cylinder")) + { + type_present = true; + } else if(params.has_child("box")) { type_present = true; @@ -1352,7 +1608,7 @@ VTKHClip::verify_params(const conduit::Node ¶ms, if(!type_present) { - info["errors"].append() = "Missing required parameter. Clip must specify a 'sphere', 'box', 'plane', or 'mulit_plane'"; + info["errors"].append() = "Missing required parameter. Clip must specify a 'sphere', 'cylinder', 'box', 'plane', or 'mulit_plane'"; res = false; } else @@ -1365,7 +1621,16 @@ VTKHClip::verify_params(const conduit::Node ¶ms, res = check_numeric("sphere/center/y",params, info, true, true) && res; res = check_numeric("sphere/center/z",params, info, true, true) && res; res = check_numeric("sphere/radius",params, info, true, true) && res; - + } + else if(params.has_child("cylinder")) + { + res = check_numeric("cylinder/center/x",params, info, true, true) && res; + res = check_numeric("cylinder/center/y",params, info, true, true) && res; + res = check_numeric("cylinder/center/z",params, info, true, true) && res; + res = check_numeric("cylinder/axis/x",params, info, true, true) && res; + res = check_numeric("cylinder/axis/y",params, info, true, true) && res; + res = check_numeric("cylinder/axis/z",params, info, true, true) && res; + res = check_numeric("cylinder/radius",params, info, true, true) && res; } else if(params.has_child("box")) { @@ -1409,16 +1674,27 @@ VTKHClip::verify_params(const conduit::Node ¶ms, std::vector valid_paths; valid_paths.push_back("topology"); valid_paths.push_back("invert"); + valid_paths.push_back("sphere/center/x"); valid_paths.push_back("sphere/center/y"); valid_paths.push_back("sphere/center/z"); valid_paths.push_back("sphere/radius"); + + valid_paths.push_back("cylinder/center/x"); + valid_paths.push_back("cylinder/center/y"); + valid_paths.push_back("cylinder/center/z"); + valid_paths.push_back("cylinder/axis/x"); + valid_paths.push_back("cylinder/axis/y"); + valid_paths.push_back("cylinder/axis/z"); + valid_paths.push_back("cylinder/radius"); + valid_paths.push_back("box/min/x"); valid_paths.push_back("box/min/y"); valid_paths.push_back("box/min/z"); valid_paths.push_back("box/max/x"); valid_paths.push_back("box/max/y"); valid_paths.push_back("box/max/z"); + valid_paths.push_back("plane/point/x"); valid_paths.push_back("plane/point/y"); valid_paths.push_back("plane/point/z"); @@ -1475,7 +1751,7 @@ VTKHClip::execute() throw_error); if(topo_name == "") { - // this creates a data object with an invalid soource + // this creates a data object with an invalid source set_output(new DataObject()); return; } @@ -1498,6 +1774,23 @@ VTKHClip::execute() double radius = get_float64(sphere["radius"], data_object); clipper.SetSphereClip(center, radius); } + else if(params().has_path("cylinder")) + { + const Node &cylinder = params()["cylinder"]; + double center[3]; + double axis[3]; + + center[0] = get_float64(cylinder["center/x"], data_object); + center[1] = get_float64(cylinder["center/y"], data_object); + center[2] = get_float64(cylinder["center/z"], data_object); + + axis[0] = get_float64(cylinder["axis/x"], data_object); + axis[1] = get_float64(cylinder["axis/y"], data_object); + axis[2] = get_float64(cylinder["axis/z"], data_object); + + double radius = get_float64(cylinder["radius"], data_object); + clipper.SetCylinderClip(center, axis, radius); + } else if(params().has_path("box")) { const Node &box = params()["box"]; diff --git a/src/libs/vtkh/filters/Clip.cpp b/src/libs/vtkh/filters/Clip.cpp index d531aa451..ffe04dcb1 100644 --- a/src/libs/vtkh/filters/Clip.cpp +++ b/src/libs/vtkh/filters/Clip.cpp @@ -170,7 +170,6 @@ Clip::SetBoxClip(const vtkm::Bounds &clipping_bounds) clipping_bounds.Y.Max, clipping_bounds.Z.Max}); - m_internals->m_func = box; } @@ -188,6 +187,28 @@ Clip::SetSphereClip(const double center[3], const double radius) m_internals->m_func = sphere; } +void +Clip::SetCylinderClip(const double center[3], + const double axis[3], + const double radius) +{ + m_do_multi_plane = false; + vtkm::Vec vec_center; + vec_center[0] = center[0]; + vec_center[1] = center[1]; + vec_center[2] = center[2]; + + vtkm::Vec vec_axis; + vec_axis[0] = axis[0]; + vec_axis[1] = axis[1]; + vec_axis[2] = axis[2]; + + vtkm::FloatDefault r = radius; + + auto cylinder = vtkm::Cylinder(vec_center, vec_axis, r); + m_internals->m_func = cylinder; +} + void Clip::SetPlaneClip(const double origin[3], const double normal[3]) { diff --git a/src/libs/vtkh/filters/Clip.hpp b/src/libs/vtkh/filters/Clip.hpp index a85132f22..05f3bffba 100644 --- a/src/libs/vtkh/filters/Clip.hpp +++ b/src/libs/vtkh/filters/Clip.hpp @@ -16,6 +16,9 @@ class VTKH_API Clip: public Filter std::string GetName() const override; void SetBoxClip(const vtkm::Bounds &clipping_bounds); void SetSphereClip(const double center[3], const double radius); + void SetCylinderClip(const double center[3], + const double axis[3], + const double radius); void SetPlaneClip(const double origin[3], const double normal[3]); void Set2PlaneClip(const double origin1[3], diff --git a/src/libs/vtkh/filters/HistSampling.cpp b/src/libs/vtkh/filters/HistSampling.cpp index 5b640d159..af07a1179 100644 --- a/src/libs/vtkh/filters/HistSampling.cpp +++ b/src/libs/vtkh/filters/HistSampling.cpp @@ -358,8 +358,8 @@ void HistSampling::DoExecute() double upper_bound = 1.; double lower_bound = 1.; - thresher.SetUpperThreshold(upper_bound); - thresher.SetLowerThreshold(lower_bound); + thresher.SetFieldUpperThreshold(upper_bound); + thresher.SetFieldLowerThreshold(lower_bound); thresher.Update(); this->m_output = thresher.GetOutput(); diff --git a/src/libs/vtkh/filters/Threshold.cpp b/src/libs/vtkh/filters/Threshold.cpp index f362aebca..82ccc723f 100644 --- a/src/libs/vtkh/filters/Threshold.cpp +++ b/src/libs/vtkh/filters/Threshold.cpp @@ -1,87 +1,274 @@ #include "Threshold.hpp" #include +#include +#include #include -#include +#include + +//---------------------------------------------------------------------------// namespace vtkh { -namespace detail + + +//---------------------------------------------------------------------------// +struct +Threshold::Internals { -} // namespace detail + typedef enum + { + UNKNOWN, + FIELD, + BOX, + PLANE, + CYLINDER, + SPHERE + } Mode; + + int m_mode; + bool m_return_all_in_range; + bool m_invert; + bool m_boundary; + // field case + vtkm::Range m_field_range; + std::string m_field_name; + + vtkm::ImplicitFunctionGeneral m_thresh_func; + + Internals(): + m_mode(Threshold::Internals::Mode::UNKNOWN), + m_return_all_in_range(false), + m_invert(false), + m_boundary(false) + {} +}; + +//---------------------------------------------------------------------------// Threshold::Threshold() +: m_internals(new Internals) { } +//---------------------------------------------------------------------------// Threshold::~Threshold() { } +//---------------------------------------------------------------------------// +std::string +Threshold::GetThresholdMode() const +{ + switch(m_internals->m_mode) + { + case Threshold::Internals::Mode::UNKNOWN: + return "unknown"; + case Threshold::Internals::Mode::FIELD: + return "field"; + case Threshold::Internals::Mode::BOX: + return "box"; + case Threshold::Internals::Mode::PLANE: + return "plane"; + case Threshold::Internals::Mode::CYLINDER: + return "cylinder"; + case Threshold::Internals::Mode::SPHERE: + return "sphere"; + default: + return "unknown"; + } +} + +//---------------------------------------------------------------------------// void -Threshold::SetUpperThreshold(const double &value) +Threshold::SetAllInRange(const bool &value) { - m_range.Max = value; + m_internals->m_return_all_in_range = value; } + +//---------------------------------------------------------------------------// +bool +Threshold::GetAllInRange() const +{ + return m_internals->m_return_all_in_range; +} + +//---------------------------------------------------------------------------// +// threshold by field +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// void -Threshold::SetLowerThreshold(const double &value) +Threshold::SetFieldUpperThreshold(const double &value) { - m_range.Min = value; + m_internals->m_mode = Threshold::Internals::Mode::FIELD; + m_internals->m_field_range.Max = value; } +//---------------------------------------------------------------------------// +void +Threshold::SetFieldLowerThreshold(const double &value) +{ + m_internals->m_mode = Threshold::Internals::Mode::FIELD; + m_internals->m_field_range.Min = value; +} + +//---------------------------------------------------------------------------// void Threshold::SetField(const std::string &field_name) { - m_field_name = field_name; + m_internals->m_mode = Threshold::Internals::Mode::FIELD; + m_internals->m_field_name = field_name; } +//---------------------------------------------------------------------------// +// invert/boundary +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +// invert +//---------------------------------------------------------------------------// void -Threshold::SetAllInRange(const bool &value) +Threshold::SetInvertThreshold(bool invert) { - m_return_all_in_range = value; + m_internals->m_invert = invert; } -double -Threshold::GetUpperThreshold() const +//---------------------------------------------------------------------------// +// boundary +//---------------------------------------------------------------------------// +void +Threshold::SetBoundaryThreshold(bool boundary) { - return m_range.Max; + m_internals->m_boundary = boundary; } -double -Threshold::GetLowerThreshold() const + +//---------------------------------------------------------------------------// +// threshold by box +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +void +Threshold::SetBoxThreshold(const vtkm::Bounds &box_bounds) { - return m_range.Min; + m_internals->m_mode = Threshold::Internals::Mode::BOX; + auto box = vtkm::Box({ box_bounds.X.Min, + box_bounds.Y.Min, + box_bounds.Z.Min}, + { box_bounds.X.Max, + box_bounds.Y.Max, + box_bounds.Z.Max}); + + m_internals->m_thresh_func = box; } -bool -Threshold::GetAllInRange() const + +//---------------------------------------------------------------------------// +// threshold by plane +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +void +Threshold::SetPlaneThreshold(const double plane_origin[3], + const double plane_normal[3]) { - return m_return_all_in_range; + m_internals->m_mode = Threshold::Internals::Mode::PLANE; + vtkm::Vec vec_origin; + vec_origin[0] = plane_origin[0]; + vec_origin[1] = plane_origin[1]; + vec_origin[2] = plane_origin[2]; + + vtkm::Vec vec_normal; + vec_normal[0] = plane_normal[0]; + vec_normal[1] = plane_normal[1]; + vec_normal[2] = plane_normal[2]; + + auto plane = vtkm::Plane(vec_origin, vec_normal); + m_internals->m_thresh_func = plane; } -std::string -Threshold::GetField() const +//---------------------------------------------------------------------------// +// threshold by cylinder +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +void +Threshold::SetCylinderThreshold(const double cylinder_center[3], + const double cylinder_axis[3], + const double cylinder_radius) { - return m_field_name; + m_internals->m_mode = Threshold::Internals::Mode::CYLINDER; + vtkm::Vec vec_center; + vec_center[0] = cylinder_center[0]; + vec_center[1] = cylinder_center[1]; + vec_center[2] = cylinder_center[2]; + + vtkm::Vec vec_axis; + vec_axis[0] = cylinder_axis[0]; + vec_axis[1] = cylinder_axis[1]; + vec_axis[2] = cylinder_axis[2]; + + vtkm::FloatDefault r = cylinder_radius; + + auto cylinder = vtkm::Cylinder(vec_center, vec_axis, r); + m_internals->m_thresh_func = cylinder; } -void Threshold::PreExecute() +//---------------------------------------------------------------------------// +// threshold by Sphere +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +void +Threshold::SetSphereThreshold(const double sphere_center[3], + const double sphere_radius) + +{ + m_internals->m_mode = Threshold::Internals::Mode::SPHERE; + vtkm::Vec vec_center; + vec_center[0] = sphere_center[0]; + vec_center[1] = sphere_center[1]; + vec_center[2] = sphere_center[2]; + vtkm::FloatDefault r = sphere_radius; + + auto sphere = vtkm::Sphere(vec_center, r); + m_internals->m_thresh_func = sphere; +} + +//---------------------------------------------------------------------------// +void +Threshold::PreExecute() { Filter::PreExecute(); - Filter::CheckForRequiredField(m_field_name); + + if(m_internals->m_mode == Threshold::Internals::Mode::UNKNOWN) + { + // error! + } + + if(m_internals->m_mode == Threshold::Internals::Mode::FIELD) + { + Filter::CheckForRequiredField(m_internals->m_field_name); + } } -void Threshold::PostExecute() + + +//---------------------------------------------------------------------------// +void +Threshold::PostExecute() { Filter::PostExecute(); } -void Threshold::DoExecute() +//---------------------------------------------------------------------------// +void +Threshold::DoExecute() { - DataSet temp_data; const int num_domains = this->m_input->GetNumberOfDomains(); @@ -90,21 +277,61 @@ void Threshold::DoExecute() vtkm::Id domain_id; vtkm::cont::DataSet dom; this->m_input->GetDomain(i, dom, domain_id); - if(!dom.HasField(m_field_name)) + + // field case + if(m_internals->m_mode == Threshold::Internals::Mode::FIELD) { - continue; - } + if(!dom.HasField(m_internals->m_field_name)) + { + continue; + } - vtkmThreshold thresholder; + vtkm::filter::entity_extraction::Threshold thresholder; + + if(m_internals->m_invert) + { + thresholder.SetInvert(true); + } + else + { + thresholder.SetInvert(false); + } - auto data_set = thresholder.Run(dom, - m_field_name, - m_range.Min, - m_range.Max, - this->GetFieldSelection(), - m_return_all_in_range); + thresholder.SetAllInRange(m_internals->m_return_all_in_range); + thresholder.SetUpperThreshold(m_internals->m_field_range.Max); + thresholder.SetLowerThreshold(m_internals->m_field_range.Min); + thresholder.SetActiveField(m_internals->m_field_name); + thresholder.SetFieldsToPass(this->GetFieldSelection()); + auto data_set = thresholder.Execute(dom); + temp_data.AddDomain(data_set, domain_id); + } + else + { + // use implicit function w/ entity extractor + vtkm::filter::entity_extraction::ExtractGeometry extractor; + if(m_internals->m_invert) + { + extractor.SetExtractInside(false); + } + else + { + extractor.SetExtractInside(true); + } - temp_data.AddDomain(data_set, domain_id); + if(m_internals->m_boundary) + { + extractor.SetExtractBoundaryCells(true); + } + else + { + extractor.SetExtractBoundaryCells(false); + } + + extractor.SetImplicitFunction(m_internals->m_thresh_func); + extractor.SetFieldsToPass(this->GetFieldSelection()); + auto data_set = extractor.Execute(dom); + temp_data.AddDomain(data_set, domain_id); + } } CleanGrid cleaner; @@ -114,6 +341,7 @@ void Threshold::DoExecute() } +//---------------------------------------------------------------------------// std::string Threshold::GetName() const { diff --git a/src/libs/vtkh/filters/Threshold.hpp b/src/libs/vtkh/filters/Threshold.hpp index ae1e4d90e..21c0ce099 100644 --- a/src/libs/vtkh/filters/Threshold.hpp +++ b/src/libs/vtkh/filters/Threshold.hpp @@ -18,22 +18,51 @@ class VTKH_API Threshold: public Filter Threshold(); virtual ~Threshold(); std::string GetName() const override; - void SetUpperThreshold(const double &value); - void SetLowerThreshold(const double &value); - void SetField(const std::string &field_name); - void SetAllInRange(const bool &value); - double GetUpperThreshold() const; - double GetLowerThreshold() const; + void SetAllInRange(const bool &value); bool GetAllInRange() const; - std::string GetField() const; + std::string GetThresholdMode() const; + + // threshold by field + void SetFieldUpperThreshold(const double &value); + void SetFieldLowerThreshold(const double &value); + void SetField(const std::string &field_name); + + // threshold by implicit function + + // invert + void SetInvertThreshold(bool invert); + + // boundary + void SetBoundaryThreshold(bool boundary); + + // threshold by box + void SetBoxThreshold(const vtkm::Bounds &box_bounds); + + // threshold by plane + void SetPlaneThreshold(const double plane_origin[3], + const double plane_normal[3]); + + // threshold by cylinder + void SetCylinderThreshold(const double cylinder_center[3], + const double cylinder_axis[3], + const double cylinder_radius); + + // threshold by Sphere + void SetSphereThreshold(const double sphere_center[3], + const double sphere_radius); + + + protected: - void PreExecute() override; + void PreExecute() override; void PostExecute() override; - void DoExecute() override; - vtkm::Range m_range; - std::string m_field_name; - bool m_return_all_in_range = false; + void DoExecute() override; + + // for vtkm implicit fun for non field cases + struct Internals; + std::shared_ptr m_internals; + }; } //namespace vtkh diff --git a/src/tests/_baseline_images/tout_clip_cylinder100.png b/src/tests/_baseline_images/tout_clip_cylinder100.png new file mode 100644 index 000000000..d0446ea93 Binary files /dev/null and b/src/tests/_baseline_images/tout_clip_cylinder100.png differ diff --git a/src/tests/_baseline_images/tout_clip_inverted_cylinder100.png b/src/tests/_baseline_images/tout_clip_inverted_cylinder100.png new file mode 100644 index 000000000..24c34b33d Binary files /dev/null and b/src/tests/_baseline_images/tout_clip_inverted_cylinder100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_box100.png b/src/tests/_baseline_images/tout_threshold_box100.png new file mode 100644 index 000000000..0f03947d7 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_box100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_cylinder100.png b/src/tests/_baseline_images/tout_threshold_cylinder100.png new file mode 100644 index 000000000..b76367a49 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_cylinder100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_inverted_3d100.png b/src/tests/_baseline_images/tout_threshold_inverted_3d100.png new file mode 100644 index 000000000..c6ab62b72 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_inverted_3d100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_inverted_box100.png b/src/tests/_baseline_images/tout_threshold_inverted_box100.png new file mode 100644 index 000000000..63f557b26 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_inverted_box100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_inverted_cylinder100.png b/src/tests/_baseline_images/tout_threshold_inverted_cylinder100.png new file mode 100644 index 000000000..f5969547d Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_inverted_cylinder100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_inverted_sphere100.png b/src/tests/_baseline_images/tout_threshold_inverted_sphere100.png new file mode 100644 index 000000000..b2f54b912 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_inverted_sphere100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_plane100.png b/src/tests/_baseline_images/tout_threshold_plane100.png new file mode 100644 index 000000000..cd6683844 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_plane100.png differ diff --git a/src/tests/_baseline_images/tout_threshold_sphere100.png b/src/tests/_baseline_images/tout_threshold_sphere100.png new file mode 100644 index 000000000..5b3100a90 Binary files /dev/null and b/src/tests/_baseline_images/tout_threshold_sphere100.png differ diff --git a/src/tests/ascent/t_ascent_clip.cpp b/src/tests/ascent/t_ascent_clip.cpp index b3a161513..40aa3c4f8 100644 --- a/src/tests/ascent/t_ascent_clip.cpp +++ b/src/tests/ascent/t_ascent_clip.cpp @@ -205,6 +205,178 @@ TEST(ascent_clip, test_clip_inverted_sphere) ASCENT_ACTIONS_DUMP(actions,output_file,msg); } +//----------------------------------------------------------------------------- +TEST(ascent_clip, test_clip_cylinder) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing 3D Rendering with Default Pipeline"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_clip_cylinder"); + + // remove old images before rendering + remove_test_image(output_file); + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "clip"; + // filter knobs + conduit::Node &clip_params = pipelines["pl1/f1/params"]; + clip_params["cylinder/radius"] = 5.; + clip_params["cylinder/center/x"] = 0.; + clip_params["cylinder/center/y"] = 0.; + clip_params["cylinder/center/z"] = 0.; + clip_params["cylinder/axis/x"] = 0.; + clip_params["cylinder/axis/y"] = 0.; + clip_params["cylinder/axis/z"] = 1.; + + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example a cylinder clip using a center, axis, and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + +//----------------------------------------------------------------------------- +TEST(ascent_clip, test_clip_inverted_cylinder) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing 3D Rendering with Default Pipeline"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_clip_inverted_cylinder"); + + // remove old images before rendering + remove_test_image(output_file); + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "clip"; + // filter knobs + conduit::Node &clip_params = pipelines["pl1/f1/params"]; + clip_params["invert"] = "true"; + clip_params["cylinder/radius"] = 5.; + clip_params["cylinder/center/x"] = 0.; + clip_params["cylinder/center/y"] = 0.; + clip_params["cylinder/center/z"] = 0.; + clip_params["cylinder/axis/x"] = 0.; + clip_params["cylinder/axis/y"] = 0.; + clip_params["cylinder/axis/z"] = 1.; + + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example an inverted cylinder clip using a center, axis, and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + //----------------------------------------------------------------------------- TEST(ascent_clip, test_clip_box) { @@ -289,7 +461,7 @@ TEST(ascent_clip, test_clip_box) // check that we created an image EXPECT_TRUE(check_test_image(output_file)); - std::string msg = "An example a blox clip"; + std::string msg = "An example of a box clip"; ASCENT_ACTIONS_DUMP(actions,output_file,msg); } diff --git a/src/tests/ascent/t_ascent_threshold.cpp b/src/tests/ascent/t_ascent_threshold.cpp index 79d23b64b..1dad122fd 100644 --- a/src/tests/ascent/t_ascent_threshold.cpp +++ b/src/tests/ascent/t_ascent_threshold.cpp @@ -118,6 +118,611 @@ TEST(ascent_threshold, test_threshold_3d) } +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_inverted_threshold_3d) +{ + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent vtkm support disabled, skipping test"); + return; + } + + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing 3D Rendering with Default Pipeline"); + + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_inverted_3d"); + + // remove old images before rendering + remove_test_image(output_file); + + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["invert"] = "true"; + thresh_params["field"] = "braid"; + thresh_params["min_value"] = -0.2; + thresh_params["max_value"] = 0.2; + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "braid"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["runtime/type"] = "ascent"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of using the threshold filter (inverted)."; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_sphere) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing threshold with a sphere"); + + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_sphere"); + + // remove old images before rendering + remove_test_image(output_file); + + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["sphere/radius"] = 11.; + thresh_params["sphere/center/x"] = 0.; + thresh_params["sphere/center/y"] = 0.; + thresh_params["sphere/center/z"] = 0.; + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + ascent.open(); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of a sphere threshold using a center and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_inverted_sphere) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing threshold with a sphere"); + + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_inverted_sphere"); + + // remove old images before rendering + remove_test_image(output_file); + + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["invert"] = "true"; + thresh_params["sphere/radius"] = 11.; + thresh_params["sphere/center/x"] = 0.; + thresh_params["sphere/center/y"] = 0.; + thresh_params["sphere/center/z"] = 0.; + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + ascent.open(); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of an inverted sphere threshold using a center and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_cylinder) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing 3D Rendering with Default Pipeline"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_cylinder"); + + // remove old images before rendering + remove_test_image(output_file); + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["cylinder/radius"] = 5.; + thresh_params["cylinder/center/x"] = 0.; + thresh_params["cylinder/center/y"] = 0.; + thresh_params["cylinder/center/z"] = 0.; + thresh_params["cylinder/axis/x"] = 0.; + thresh_params["cylinder/axis/y"] = 0.; + thresh_params["cylinder/axis/z"] = 1.; + + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of a cylinder threshold using a center, axis, and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + + + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_inverted_cylinder) +{ + // the vtkm runtime is currently our only rendering runtime + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping test"); + return; + } + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing 3D Rendering with Default Pipeline"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_inverted_cylinder"); + + // remove old images before rendering + remove_test_image(output_file); + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["invert"] = "true"; + thresh_params["cylinder/radius"] = 5.; + thresh_params["cylinder/center/x"] = 0.; + thresh_params["cylinder/center/y"] = 0.; + thresh_params["cylinder/center/z"] = 0.; + thresh_params["cylinder/axis/x"] = 0.; + thresh_params["cylinder/axis/y"] = 0.; + thresh_params["cylinder/axis/z"] = 1.; + + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of an inverted cylinder threshold using a center, axis, and radius"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_box) +{ + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping 3D default" + "Pipeline test"); + + return; + } + + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing Box Threshold"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_box"); + + // remove old images before rendering + remove_test_image(output_file); + + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["box/min/x"] = 0.; + thresh_params["box/min/y"] = 0.; + thresh_params["box/min/z"] = 0.; + thresh_params["box/max/x"] = 10.01; // <= + thresh_params["box/max/y"] = 10.01; + thresh_params["box/max/z"] = 10.01; + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["runtime/type"] = "ascent"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of a box threshold"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + +//----------------------------------------------------------------------------- +TEST(ascent_threshold, test_threshold_inverted_box) +{ + Node n; + ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent support disabled, skipping 3D default" + "Pipeline test"); + + return; + } + + + // + // Create an example mesh. + // + Node data, verify_info; + conduit::blueprint::mesh::examples::braid("hexs", + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + EXAMPLE_MESH_SIDE_DIM, + data); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing Box Threshold"); + + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_threshold_inverted_box"); + + // remove old images before rendering + remove_test_image(output_file); + + + // + // Create the actions. + // + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "threshold"; + // filter knobs + conduit::Node &thresh_params = pipelines["pl1/f1/params"]; + thresh_params["invert"] = "true"; + thresh_params["box/min/x"] = 0.; + thresh_params["box/min/y"] = 0.; + thresh_params["box/min/z"] = 0.; + thresh_params["box/max/x"] = 10.01; // <= + thresh_params["box/max/y"] = 10.01; + thresh_params["box/max/z"] = 10.01; + + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "radial"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = output_file; + + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines= actions.append(); + add_pipelines["action"] = "add_pipelines"; + add_pipelines["pipelines"] = pipelines; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["runtime/type"] = "ascent"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + // check that we created an image + EXPECT_TRUE(check_test_image(output_file)); + std::string msg = "An example of an inverted box threshold"; + ASCENT_ACTIONS_DUMP(actions,output_file,msg); +} + + //----------------------------------------------------------------------------- int main(int argc, char* argv[]) { diff --git a/src/tests/vtkh/t_vtk-h_empty_data.cpp b/src/tests/vtkh/t_vtk-h_empty_data.cpp index 1dcf66fb2..ddbc8b2ae 100644 --- a/src/tests/vtkh/t_vtk-h_empty_data.cpp +++ b/src/tests/vtkh/t_vtk-h_empty_data.cpp @@ -87,8 +87,8 @@ TEST(vtkh_emtpy_data, vtkh_empty_vtkm) double upper_bound = 1.; double lower_bound = 0.; - thresher.SetUpperThreshold(upper_bound); - thresher.SetLowerThreshold(lower_bound); + thresher.SetFieldUpperThreshold(upper_bound); + thresher.SetFieldLowerThreshold(lower_bound); thresher.Update(); vtkh::DataSet *thresh_output = thresher.GetOutput(); diff --git a/src/tests/vtkh/t_vtk-h_threshold.cpp b/src/tests/vtkh/t_vtk-h_threshold.cpp index 733e565c8..1a97be1ce 100644 --- a/src/tests/vtkh/t_vtk-h_threshold.cpp +++ b/src/tests/vtkh/t_vtk-h_threshold.cpp @@ -40,8 +40,8 @@ TEST(vtkh_threshold, vtkh_serial_threshold) double upper_bound = (float)base_size * (float)num_blocks * 0.5f; double lower_bound = 0; - thresher.SetUpperThreshold(upper_bound); - thresher.SetLowerThreshold(lower_bound); + thresher.SetFieldUpperThreshold(upper_bound); + thresher.SetFieldLowerThreshold(lower_bound); thresher.Update(); vtkh::DataSet *output = thresher.GetOutput(); vtkm::Bounds bounds = output->GetGlobalBounds();