mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add MapFieldPermutation function
This function is compiled into the vtkm_filter library, so all filters can implement this type of mapping without providing their own version of compiling it. Because we only compile it once, we provide more types to convert. Hopefully the total compile time balances out.
This commit is contained in:
parent
b1f288aaea
commit
2383a7fffd
@ -45,6 +45,7 @@ set(headers
|
|||||||
ImageMedian.h
|
ImageMedian.h
|
||||||
Lagrangian.h
|
Lagrangian.h
|
||||||
LagrangianStructures.h
|
LagrangianStructures.h
|
||||||
|
MapFieldMergeAverage.h
|
||||||
MapFieldPermutation.h
|
MapFieldPermutation.h
|
||||||
Mask.h
|
Mask.h
|
||||||
MaskPoints.h
|
MaskPoints.h
|
||||||
@ -155,6 +156,7 @@ set(sources_device
|
|||||||
GradientScalar.cxx
|
GradientScalar.cxx
|
||||||
GradientUniformPoints.cxx
|
GradientUniformPoints.cxx
|
||||||
GradientVector.cxx
|
GradientVector.cxx
|
||||||
|
MapFieldMergeAverage.cxx
|
||||||
MapFieldPermutation.cxx
|
MapFieldPermutation.cxx
|
||||||
PointAverage.cxx
|
PointAverage.cxx
|
||||||
Threshold.cxx
|
Threshold.cxx
|
||||||
|
69
vtkm/filter/MapFieldMergeAverage.cxx
Normal file
69
vtkm/filter/MapFieldMergeAverage.cxx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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 <vtkm/filter/MapFieldMergeAverage.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
|
||||||
|
#include <vtkm/worklet/AverageByKey.h>
|
||||||
|
|
||||||
|
#include <vtkm/filter/PolicyDefault.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct DoMapFieldMerge
|
||||||
|
{
|
||||||
|
bool CalledMap = false;
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandle<T, S>& inputArray,
|
||||||
|
const vtkm::worklet::internal::KeysBase& keys,
|
||||||
|
vtkm::cont::VariantArrayHandle& output)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<T> outputArray = vtkm::worklet::AverageByKey::Run(keys, inputArray);
|
||||||
|
output = vtkm::cont::VariantArrayHandle(outputArray);
|
||||||
|
this->CalledMap = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
bool vtkm::filter::MapFieldMergeAverage(const vtkm::cont::Field& inputField,
|
||||||
|
const vtkm::worklet::internal::KeysBase& keys,
|
||||||
|
vtkm::cont::Field& outputField)
|
||||||
|
{
|
||||||
|
vtkm::cont::VariantArrayHandle outputArray;
|
||||||
|
DoMapFieldMerge functor;
|
||||||
|
inputField.GetData().ResetTypes<vtkm::TypeListAll>().CastAndCall(
|
||||||
|
vtkm::filter::PolicyDefault::StorageList{}, functor, keys, outputArray);
|
||||||
|
if (functor.CalledMap)
|
||||||
|
{
|
||||||
|
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Faild to map field " << inputField.GetName());
|
||||||
|
}
|
||||||
|
return functor.CalledMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vtkm::filter::MapFieldMergeAverage(const vtkm::cont::Field& inputField,
|
||||||
|
const vtkm::worklet::internal::KeysBase& keys,
|
||||||
|
vtkm::cont::DataSet& outputData)
|
||||||
|
{
|
||||||
|
vtkm::cont::Field outputField;
|
||||||
|
bool success = vtkm::filter::MapFieldMergeAverage(inputField, keys, outputField);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
outputData.AddField(outputField);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
73
vtkm/filter/MapFieldMergeAverage.h
Normal file
73
vtkm/filter/MapFieldMergeAverage.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_MapFieldMergeAverage_h
|
||||||
|
#define vtk_m_filter_MapFieldMergeAverage_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
|
#include <vtkm/cont/DataSet.h>
|
||||||
|
#include <vtkm/cont/Field.h>
|
||||||
|
|
||||||
|
#include <vtkm/worklet/Keys.h>
|
||||||
|
|
||||||
|
#include <vtkm/filter/vtkm_filter_export.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
|
||||||
|
/// \brief Maps a field by merging entries based on a keys object.
|
||||||
|
///
|
||||||
|
/// This method will create a new field containing the data from the provided `inputField` but but
|
||||||
|
/// with groups of entities merged together. The input `keys` object encapsulates which elements
|
||||||
|
/// should be merged together. A group of elements merged together will be averaged. The result is
|
||||||
|
/// placed in `outputField`.
|
||||||
|
///
|
||||||
|
/// The intention of this method is to implement the `MapFieldOntoOutput` methods in filters (many
|
||||||
|
/// of which require this merge of a field), but can be used in other places as well.
|
||||||
|
///
|
||||||
|
/// `outputField` is set to have the same metadata as the input. If the metadata needs to change
|
||||||
|
/// (such as the name or the association) that should be done after the function returns.
|
||||||
|
///
|
||||||
|
/// This function returns whether the field was successfully merged. If the returned result is
|
||||||
|
/// `true`, then the results in `outputField` are valid. If it is `false`, then `outputField`
|
||||||
|
/// should not be used.
|
||||||
|
///
|
||||||
|
VTKM_FILTER_EXPORT VTKM_CONT bool MapFieldMergeAverage(
|
||||||
|
const vtkm::cont::Field& inputField,
|
||||||
|
const vtkm::worklet::internal::KeysBase& keys,
|
||||||
|
vtkm::cont::Field& outputField);
|
||||||
|
|
||||||
|
/// \brief Maps a field by merging entries based on a keys object.
|
||||||
|
///
|
||||||
|
/// This method will create a new field containing the data from the provided `inputField` but but
|
||||||
|
/// with groups of entities merged together. The input `keys` object encapsulates which elements
|
||||||
|
/// should be merged together. A group of elements merged together will be averaged.
|
||||||
|
///
|
||||||
|
/// The intention of this method is to implement the `MapFieldOntoOutput` methods in filters (many
|
||||||
|
/// of which require this merge of a field), but can be used in other places as well. The
|
||||||
|
/// resulting field is put in the given `DataSet`.
|
||||||
|
///
|
||||||
|
/// The returned `Field` has the same metadata as the input. If the metadata needs to change (such
|
||||||
|
/// as the name or the association), then a different form of `MapFieldMergeAverage` should be used.
|
||||||
|
///
|
||||||
|
/// This function returns whether the field was successfully merged. If the returned result is
|
||||||
|
/// `true`, then `outputData` has the merged field. If it is `false`, then the field is not
|
||||||
|
/// placed in `outputData`.
|
||||||
|
///
|
||||||
|
VTKM_FILTER_EXPORT VTKM_CONT bool MapFieldMergeAverage(
|
||||||
|
const vtkm::cont::Field& inputField,
|
||||||
|
const vtkm::worklet::internal::KeysBase& keys,
|
||||||
|
vtkm::cont::DataSet& outputData);
|
||||||
|
}
|
||||||
|
} // namespace vtkm::filter
|
||||||
|
|
||||||
|
#endif //vtk_m_filter_MapFieldMergeAverage_h
|
@ -39,6 +39,7 @@ set(unit_tests
|
|||||||
UnitTestImageMedianFilter.cxx
|
UnitTestImageMedianFilter.cxx
|
||||||
UnitTestLagrangianFilter.cxx
|
UnitTestLagrangianFilter.cxx
|
||||||
UnitTestLagrangianStructuresFilter.cxx
|
UnitTestLagrangianStructuresFilter.cxx
|
||||||
|
UnitTestMapFieldMergeAverage.cxx
|
||||||
UnitTestMapFieldPermutation.cxx
|
UnitTestMapFieldPermutation.cxx
|
||||||
UnitTestMaskFilter.cxx
|
UnitTestMaskFilter.cxx
|
||||||
UnitTestMaskPointsFilter.cxx
|
UnitTestMaskPointsFilter.cxx
|
||||||
|
151
vtkm/filter/testing/UnitTestMapFieldMergeAverage.cxx
Normal file
151
vtkm/filter/testing/UnitTestMapFieldMergeAverage.cxx
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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 <vtkm/filter/MapFieldMergeAverage.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||||
|
#include <vtkm/cont/Field.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr vtkm::Id ARRAY_SIZE = 26;
|
||||||
|
constexpr vtkm::Id3 ARRAY3_DIM = { 3, 3, 3 };
|
||||||
|
constexpr vtkm::Id REDUCED_SIZE = 7;
|
||||||
|
|
||||||
|
vtkm::worklet::Keys<vtkm::Id> MakeKeys(vtkm::Id originalArraySize)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> keyArray;
|
||||||
|
keyArray.Allocate(originalArraySize);
|
||||||
|
{
|
||||||
|
auto portal = keyArray.WritePortal();
|
||||||
|
for (vtkm::Id i = 0; i < originalArraySize; ++i)
|
||||||
|
{
|
||||||
|
portal.Set(i, i % REDUCED_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vtkm::worklet::Keys<vtkm::Id>(keyArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array of the expected output of mapping the given array using the keys returned from
|
||||||
|
// MakeKeys but with a different mechanism.
|
||||||
|
template <typename T, typename S>
|
||||||
|
vtkm::cont::ArrayHandle<T> MakeExpectedOutput(const vtkm::cont::ArrayHandle<T, S>& inputArray)
|
||||||
|
{
|
||||||
|
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||||
|
|
||||||
|
auto inputPortal = inputArray.ReadPortal();
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T> outputArray;
|
||||||
|
outputArray.Allocate(REDUCED_SIZE);
|
||||||
|
auto outputPortal = outputArray.WritePortal();
|
||||||
|
|
||||||
|
for (vtkm::Id reducedI = 0; reducedI < REDUCED_SIZE; ++reducedI)
|
||||||
|
{
|
||||||
|
T sum = vtkm::TypeTraits<T>::ZeroInitialization();
|
||||||
|
ComponentType num = 0;
|
||||||
|
for (vtkm::Id fullI = reducedI; fullI < inputArray.GetNumberOfValues(); fullI += REDUCED_SIZE)
|
||||||
|
{
|
||||||
|
sum = sum + inputPortal.Get(fullI);
|
||||||
|
num = num + ComponentType(1);
|
||||||
|
}
|
||||||
|
outputPortal.Set(reducedI, sum / T(num));
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
void TryArray(const vtkm::cont::ArrayHandle<T, S>& inputArray)
|
||||||
|
{
|
||||||
|
std::cout << "Input" << std::endl;
|
||||||
|
vtkm::cont::printSummary_ArrayHandle(inputArray, std::cout);
|
||||||
|
|
||||||
|
vtkm::cont::Field::Association association =
|
||||||
|
((sizeof(T) < 8) ? vtkm::cont::Field::Association::POINTS
|
||||||
|
: vtkm::cont::Field::Association::CELL_SET);
|
||||||
|
|
||||||
|
vtkm::cont::Field inputField("my-array", association, inputArray);
|
||||||
|
|
||||||
|
vtkm::worklet::Keys<vtkm::Id> keys = MakeKeys(inputArray.GetNumberOfValues());
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T> expectedOutputArray = MakeExpectedOutput(inputArray);
|
||||||
|
std::cout << "Expected output" << std::endl;
|
||||||
|
vtkm::cont::printSummary_ArrayHandle(expectedOutputArray, std::cout);
|
||||||
|
|
||||||
|
vtkm::cont::Field outputField;
|
||||||
|
bool result = vtkm::filter::MapFieldMergeAverage(inputField, keys, outputField);
|
||||||
|
VTKM_TEST_ASSERT(result, "Could not map the array.");
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(outputField.GetAssociation() == association);
|
||||||
|
VTKM_TEST_ASSERT(outputField.GetName() == "my-array");
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T> outputArray;
|
||||||
|
outputField.GetData().CopyTo(outputArray);
|
||||||
|
std::cout << "Actual output" << std::endl;
|
||||||
|
vtkm::cont::printSummary_ArrayHandle(outputArray, std::cout);
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(test_equal_portals(expectedOutputArray.ReadPortal(), outputArray.ReadPortal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void TryType(T)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<T> inputArray;
|
||||||
|
inputArray.Allocate(ARRAY_SIZE);
|
||||||
|
SetPortal(inputArray.WritePortal());
|
||||||
|
TryArray(inputArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TryTypeFunctor
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
void operator()(T x) const
|
||||||
|
{
|
||||||
|
TryType(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void TryCartesianProduct()
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> axes[3];
|
||||||
|
for (vtkm::IdComponent i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
axes[i].Allocate(ARRAY3_DIM[i]);
|
||||||
|
SetPortal(axes[i].WritePortal());
|
||||||
|
}
|
||||||
|
|
||||||
|
TryArray(vtkm::cont::make_ArrayHandleCartesianProduct(axes[0], axes[1], axes[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoTest()
|
||||||
|
{
|
||||||
|
std::cout << "**** Test Basic Arrays *****" << std::endl;
|
||||||
|
vtkm::testing::Testing::TryTypes(TryTypeFunctor{});
|
||||||
|
|
||||||
|
std::cout << std::endl << "**** Test Uniform Point Coordiantes *****" << std::endl;
|
||||||
|
TryArray(vtkm::cont::ArrayHandleUniformPointCoordinates(ARRAY3_DIM));
|
||||||
|
|
||||||
|
std::cout << std::endl << "**** Test Cartesian Product *****" << std::endl;
|
||||||
|
TryCartesianProduct();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
int UnitTestMapFieldMergeAverage(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user