Add CreateResult to NewFilter and absorb field mapping

The original version of `Filter` classes had a helper header file named
`CreateResult.h` that had several forms of a `CreateResult` function that
helped correctly create the `DataSet` to be returned from a filter's
`DoExecute`. With the move to the `NewFilter` structure, these functions
did not line up very well with how `DataSet`s should actually be created.

A replacement for these functions have been added as protected helper
methods to `NewFilter` and `NewFilterField`. In addition to moving them
into the filter themselves, the behavior of `CreateResult` has been merged
with the map field to output functionality. The original implementation of
`Filter` did this mapping internally in a different step. The first design
of `NewFilter` required the filter implementer to call a
`MapFieldsOntoOutput` themselves. This new implementation wraps the
functionality of `CreateResult` and `MapFieldsOntoOutput` together so that
the `DataSet` will be created correctly with a single call to
`CreateResult`. This makes it easier to correctly create the output.
This commit is contained in:
Kenneth Moreland 2022-01-26 17:11:11 -07:00
parent 4e047eae64
commit 5bd60a0b77
22 changed files with 313 additions and 144 deletions

@ -0,0 +1,18 @@
# Add `CreateResult` to `NewFilter` and absorb field mapping
The original version of `Filter` classes had a helper header file named
`CreateResult.h` that had several forms of a `CreateResult` function that
helped correctly create the `DataSet` to be returned from a filter's
`DoExecute`. With the move to the `NewFilter` structure, these functions
did not line up very well with how `DataSet`s should actually be created.
A replacement for these functions have been added as protected helper
methods to `NewFilter` and `NewFilterField`. In addition to moving them
into the filter themselves, the behavior of `CreateResult` has been merged
with the map field to output functionality. The original implementation of
`Filter` did this mapping internally in a different step. The first design
of `NewFilter` required the filter implementer to call a
`MapFieldsOntoOutput` themselves. This new implementation wraps the
functionality of `CreateResult` and `MapFieldsOntoOutput` together so that
the `DataSet` will be created correctly with a single call to
`CreateResult`. This makes it easier to correctly create the output.

@ -221,6 +221,14 @@ public:
vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name);
//@}
/// Returns an `std::vector` of `CoordinateSystem`s held in this `DataSet`.
///
VTKM_CONT
std::vector<vtkm::cont::CoordinateSystem> GetCoordinateSystems() const
{
return this->CoordSystems;
}
template <typename CellSetType>
VTKM_CONT void SetCellSet(const CellSetType& cellSet)
{

@ -16,6 +16,9 @@
#include <vtkm/filter/FieldMetadata.h>
// Once all the filters move to the NewFilter base classes, this header should
// be deprecated.
namespace vtkm
{
namespace filter

@ -100,6 +100,17 @@ vtkm::cont::PartitionedDataSet NewFilter::Execute(const vtkm::cont::PartitionedD
return output;
}
vtkm::cont::DataSet NewFilter::CreateResult(const vtkm::cont::DataSet& inDataSet) const
{
vtkm::cont::DataSet clone;
clone.CopyStructure(inDataSet);
this->MapFieldsOntoOutput(
inDataSet, clone, [](vtkm::cont::DataSet& out, const vtkm::cont::Field& fieldToPass) {
out.AddField(fieldToPass);
});
return clone;
}
vtkm::Id NewFilter::DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input)
{
vtkm::Id numDS = input.GetNumberOfPartitions();

@ -128,17 +128,18 @@ namespace filter
/// full control over the execution, including any mapping of fields to output (described in next
/// sub-section).
///
/// \subsection FilterMappingFields MapFieldsOntoOutput
/// \subsection Creating results and mapping fields
///
/// For subclasses that map input fields into output fields, the implementation of its
/// `DoExecute(DataSet&)` should call `NewFilter::MapFieldsOntoOutput` with a properly defined
/// `Mapper`, before returning the output DataSet. For example:
/// `DoExecute(DataSet&)` should create the `DataSet` to be returned with a call to
/// `NewFilter::CreateResult` or a similar method in a subclass (such as
/// `NewFilterField::CreateResultField`).
///
/// \code{cpp}
/// VTKM_CONT DataSet SomeFilter::DoExecute(const vtkm::cont::DataSet& input)
/// {
/// vtkm::cont::DataSet output;
/// output = ... // Generation of the new DataSet
/// vtkm::cont::UnknownCellSet outCellSet;
/// outCellSet = ... // Generation of the new CellSet
///
/// // Mapper is a callable object (function object, lambda, etc.) that takes an input Field
/// // and maps it to an output Field and then add the output Field to the output DataSet
@ -146,18 +147,19 @@ namespace filter
/// auto outputField = ... // Business logic for mapping input field to output field
/// output.AddField(outputField);
/// };
/// this->MapFieldsOntoOutput(input, output, mapper);
///
/// return output;
/// // This passes coordinate systems directly from input to output. If the points of
/// // the cell set change at all, they will have to be mapped by hand.
/// return this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper);
/// }
/// \endcode
///
/// `MapFieldsOntoOutput` iterates through each `FieldToPass` in the input DataSet and calls the
/// Mapper to map the input Field to output Field. For simple filters that just pass on input
/// In addition to creating a new `DataSet` filled with the proper cell structure and coordinate
/// systems, `CreateResult` iterates through each `FieldToPass` in the input DataSet and calls the
/// FieldMapper to map the input Field to output Field. For simple filters that just pass on input
/// fields to the output DataSet without any computation, an overload of
/// `MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)` is also
/// `CreateResult(const vtkm::cont::DataSet& input)` is also
/// provided as a convenience that uses the default mapper which trivially adds input Field to
/// output DaaSet (via a shallow copy).
/// output DataSet (via a shallow copy).
///
/// \subsection FilterThreadSafety CanThread
///
@ -302,24 +304,115 @@ public:
protected:
vtkm::cont::Invoker Invoke;
template <typename Mapper>
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input,
vtkm::cont::DataSet& output,
Mapper&& mapper)
/// \brief Create the output data set for `DoExecute`.
///
/// This form of `CreateResult` will create an output data set with the same cell
/// structure and coordinate system as the input and pass all fields (as requested
/// by the `Filter` state).
///
/// \param[in] inDataSet The input data set being modified (usually the one passed into
/// `DoExecute`). The returned `DataSet` is filled with the cell set, coordinate system, and
/// fields of `inDataSet` (as selected by the `FieldsToPass` state of the filter).
///
VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet) const;
/// \brief Create the output data set for `DoExecute`.
///
/// This form of `CreateResult` will create an output data set with the given `CellSet`. You must
/// also provide a field mapper function, which is a function that takes the output `DataSet`
/// being created and a `Field` from the input and then applies any necessary transformations to
/// the field array and adds it to the `DataSet`.
///
/// This form of `CreateResult` returns a `DataSet` with _no_ coordinate systems. The calling
/// program must add any necessary `CoordinateSystem`s.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultCellSet The `CellSet` of the output will be set to this.
/// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first
/// argument and a `Field` as its second argument. The `DataSet` is the data being
/// created and will eventually be returned by `CreateResult`. The `Field` comes from
/// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then
/// add the resulting field to the `DataSet`. If the mapping is not possible, then
/// the function should do nothing.
///
template <typename FieldMapper>
VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::UnknownCellSet& resultCellSet,
FieldMapper&& fieldMapper) const
{
for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc)
{
auto field = input.GetField(cc);
if (this->GetFieldsToPass().IsFieldSelected(field))
{
mapper(output, field);
}
}
vtkm::cont::DataSet outDataSet;
outDataSet.SetCellSet(resultCellSet);
this->MapFieldsOntoOutput(inDataSet, outDataSet, fieldMapper);
return outDataSet;
}
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)
/// \brief Create the output data set for `DoExecute`.
///
/// This form of `CreateResult` will create an output data set with the given `CellSet`
/// and set of `CoordinateSystem`s. You must also provide a field mapper function, which
/// is a function that takes the output `DataSet` being created and a `Field` from the
/// input and then applies any necessary transformations to the field array and adds it
/// to the `DataSet`.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultCellSet The `CellSet` of the output will be set to this.
/// \param[in] resultCoordSystems These `CoordinateSystem`s will be added to the output.
/// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first
/// argument and a `Field` as its second argument. The `DataSet` is the data being
/// created and will eventually be returned by `CreateResult`. The `Field` comes from
/// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then
/// add the resulting field to the `DataSet`. If the mapping is not possible, then
/// the function should do nothing.
///
template <typename FieldMapper>
VTKM_CONT vtkm::cont::DataSet CreateResult(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::UnknownCellSet& resultCellSet,
const std::vector<vtkm::cont::CoordinateSystem>& resultCoordSystems,
FieldMapper&& fieldMapper) const
{
this->MapFieldsOntoOutput(input, output, defaultMapper);
vtkm::cont::DataSet outDataSet = this->CreateResult(inDataSet, resultCellSet, fieldMapper);
for (auto&& cs : resultCoordSystems)
{
outDataSet.AddCoordinateSystem(cs);
}
return outDataSet;
}
/// \brief Create the output data set for `DoExecute`.
///
/// This form of `CreateResult` will create an output data set with the given `CellSet`
/// and `CoordinateSystem`. You must also provide a field mapper function, which is a
/// function that takes the output `DataSet` being created and a `Field` from the input
/// and then applies any necessary transformations to the field array and adds it to
/// the `DataSet`.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultCellSet The `CellSet` of the output will be set to this.
/// \param[in] resultCoordSystem This `CoordinateSystem` will be added to the output.
/// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first
/// argument and a `Field` as its second argument. The `DataSet` is the data being
/// created and will eventually be returned by `CreateResult`. The `Field` comes from
/// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then
/// add the resulting field to the `DataSet`. If the mapping is not possible, then
/// the function should do nothing.
///
template <typename FieldMapper>
VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::UnknownCellSet& resultCellSet,
const vtkm::cont::CoordinateSystem& resultCoordSystem,
FieldMapper&& fieldMapper) const
{
return this->CreateResult(inDataSet,
resultCellSet,
std::vector<vtkm::cont::CoordinateSystem>{ resultCoordSystem },
fieldMapper);
}
VTKM_CONT virtual vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) = 0;
@ -330,10 +423,20 @@ private:
VTKM_CONT
virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input);
static void defaultMapper(vtkm::cont::DataSet& output, const vtkm::cont::Field& field)
template <typename FieldMapper>
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input,
vtkm::cont::DataSet& output,
FieldMapper&& fieldMapper) const
{
output.AddField(field);
};
for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc)
{
auto field = input.GetField(cc);
if (this->GetFieldsToPass().IsFieldSelected(field))
{
fieldMapper(output, field);
}
}
}
vtkm::filter::FieldSelection FieldsToPass = vtkm::filter::FieldSelection::MODE_ALL;
bool RunFilterWithMultipleThreads = false;

@ -14,6 +14,16 @@ namespace vtkm
namespace filter
{
vtkm::cont::DataSet NewFilterField::CreateResultField(const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::Field& resultField) const
{
vtkm::cont::DataSet outDataSet = this->CreateResult(inDataSet);
outDataSet.AddField(resultField);
VTKM_ASSERT(!resultField.GetName().empty());
VTKM_ASSERT(outDataSet.HasField(resultField.GetName(), resultField.GetAssociation()));
return outDataSet;
}
void NewFilterField::ResizeIfNeeded(size_t index_st)
{
if (this->ActiveFieldNames.size() <= index_st)

@ -161,6 +161,7 @@ protected:
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
}
private:
template <vtkm::IdComponent VecSize>
struct ScalarToVec
@ -190,6 +191,97 @@ protected:
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
}
/// \brief Create the output data set for `DoExecute`
///
/// This form of `CreateResult` will create an output data set with the same cell
/// structure and coordinate system as the input and pass all fields (as requested
/// by the `Filter` state). Additionally, it will add the provided field to the
/// result.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultField A `Field` that is added to the returned `DataSet`.
///
VTKM_CONT vtkm::cont::DataSet CreateResultField(const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::Field& resultField) const;
/// \brief Create the output data set for `DoExecute`
///
/// This form of `CreateResult` will create an output data set with the same cell
/// structure and coordinate system as the input and pass all fields (as requested
/// by the `Filter` state). Additionally, it will add a field matching the provided
/// specifications to the result.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultFieldName The name of the field added to the returned `DataSet`.
/// \param[in] resultFieldAssociation The association of the field (e.g. point or cell)
/// added to the returned `DataSet`.
/// \param[in] resultFieldArray An array containing the data for the field added to the
/// returned `DataSet`.
///
VTKM_CONT vtkm::cont::DataSet CreateResultField(
const vtkm::cont::DataSet& inDataSet,
const std::string& resultFieldName,
vtkm::cont::Field::Association resultFieldAssociation,
const vtkm::cont::UnknownArrayHandle& resultFieldArray) const
{
return this->CreateResultField(
inDataSet, vtkm::cont::Field{ resultFieldName, resultFieldAssociation, resultFieldArray });
}
/// \brief Create the output data set for `DoExecute`
///
/// This form of `CreateResult` will create an output data set with the same cell
/// structure and coordinate system as the input and pass all fields (as requested
/// by the `Filter` state). Additionally, it will add a point field matching the
/// provided specifications to the result.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultFieldName The name of the field added to the returned `DataSet`.
/// \param[in] resultFieldArray An array containing the data for the field added to the
/// returned `DataSet`.
///
VTKM_CONT vtkm::cont::DataSet CreateResultFieldPoint(
const vtkm::cont::DataSet& inDataSet,
const std::string& resultFieldName,
const vtkm::cont::UnknownArrayHandle& resultFieldArray) const
{
return this->CreateResultField(inDataSet,
vtkm::cont::Field{ resultFieldName,
vtkm::cont::Field::Association::POINTS,
resultFieldArray });
}
/// \brief Create the output data set for `DoExecute`
///
/// This form of `CreateResult` will create an output data set with the same cell
/// structure and coordinate system as the input and pass all fields (as requested
/// by the `Filter` state). Additionally, it will add a cell field matching the
/// provided specifications to the result.
///
/// \param[in] inDataSet The input data set being modified (usually the one passed
/// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet`
/// (as selected by the `FieldsToPass` state of the filter).
/// \param[in] resultFieldName The name of the field added to the returned `DataSet`.
/// \param[in] resultFieldArray An array containing the data for the field added to the
/// returned `DataSet`.
///
VTKM_CONT vtkm::cont::DataSet CreateResultFieldCell(
const vtkm::cont::DataSet& inDataSet,
const std::string& resultFieldName,
const vtkm::cont::UnknownArrayHandle& resultFieldArray) const
{
return this->CreateResultField(inDataSet,
vtkm::cont::Field{ resultFieldName,
vtkm::cont::Field::Association::CELL_SET,
resultFieldArray });
}
private:
void ResizeIfNeeded(size_t index_st);

@ -31,7 +31,7 @@ struct SharedStates
}
// New Filter Design: DoMapField is now a free function in an anonymous namespace. It should be
// considered as a convenience/extension to the lambda passed to the MapFieldsOntoOutput.
// considered as a convenience/extension to the lambda passed to CreateResult.
// Being a free function discourages the developer to "pass" mutable states from DoExecute phase
// to DoMapField phase via data member. However, there is nothing to prevent developer doing
// stupid thing to circumvent the protection. One example here is that the developer could
@ -167,17 +167,18 @@ vtkm::cont::DataSet CleanGrid::GenerateOutput(const vtkm::cont::DataSet& inData,
outputCellSet = worklets.CellCompactor.Run(outputCellSet);
}
// Construct resulting data set with new cell sets
vtkm::cont::DataSet outData;
outData.SetCellSet(outputCellSet);
// Pass the coordinate systems
for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
{
outData.AddCoordinateSystem(outputCoordinateSystems[coordSystemIndex]);
}
return outData;
// New Filter Design: We pass the actions needed to be done as a lambda to the generic
// CreateResult method. CreateResult now acts as thrust::transform_if on the
// Fields. Shared mutable state is captured by the lambda. We could also put all the logic
// of field mapping in the lambda. However, it is cleaner to put it in the filter specific
// implementation of DoMapField which takes mutable state as an extra parameter.
//
// For filters that do not need to do interpolation for mapping fields, we provide an overload
// that does not take the extra arguments and just AddField.
auto mapper = [&, this](auto& outDataSet, const auto& f) {
DoMapField(outDataSet, f, *this, worklets);
};
return this->CreateResult(inData, outputCellSet, outputCoordinateSystems, mapper);
}
vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::DataSet& inData)
@ -221,22 +222,7 @@ vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::DataSet& inData)
// New Filter Design: The share, mutable state is pass to other methods via parameter, not as
// a data member.
auto outData = this->GenerateOutput(inData, outputCellSet, worklets);
// New Filter Design: We pass the actions needed to be done as a lambda to the generic
// MapFieldsOntoOutput method. MapFieldsOntoOutput now acts as thrust::transform_if on the
// Fields. Shared mutable state is captured by the lambda. We could also put all the logic
// of field mapping in the lambda. However, it is cleaner to put it in the filter specific
// implementation of DoMapField which takes mutable state as an extra parameter.
//
// For filters that do not need to do interpolation for mapping fields, we provide an overload
// that does not take the extra arguments and just AddField.
auto mapper = [&, this](auto& outDataSet, const auto& f) {
DoMapField(outDataSet, f, *this, worklets);
};
this->MapFieldsOntoOutput(inData, outData, mapper);
return outData;
return this->GenerateOutput(inData, outputCellSet, worklets);
}
} //namespace clean_grid
} //namespace filter

@ -24,10 +24,7 @@ VTKM_CONT vtkm::cont::DataSet CellSetConnectivity::DoExecute(const vtkm::cont::D
vtkm::worklet::connectivity::CellSetConnectivity().Run(input.GetCellSet(), component);
auto output = CreateResultFieldCell(input, component, this->GetOutputFieldName());
this->MapFieldsOntoOutput(input, output);
return output;
return this->CreateResultFieldCell(input, this->GetOutputFieldName(), component);
}
} // namespace connected_components
} // namespace filter

@ -35,10 +35,7 @@ VTKM_CONT vtkm::cont::DataSet ImageConnectivity::DoExecute(const vtkm::cont::Dat
const auto& fieldArray = field.GetData();
this->CastAndCallScalarField(fieldArray, resolveType);
auto output = CreateResultFieldPoint(input, component, this->GetOutputFieldName());
this->MapFieldsOntoOutput(input, output);
return output;
return this->CreateResultFieldPoint(input, this->GetOutputFieldName(), component);
}
} // namespace connected_components
} // namespace filter

@ -56,11 +56,11 @@ vtkm::cont::DataSet ExternalFaces::GenerateOutput(const vtkm::cont::DataSet& inp
}
//4. create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
return output;
auto mapper = [&, this](auto& result, const auto& f) {
// New Design: We are still using the old MapFieldOntoOutput to demonstrate the transition
this->MapFieldOntoOutput(result, f);
};
return this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper);
}
//-----------------------------------------------------------------------------
@ -87,11 +87,6 @@ vtkm::cont::DataSet ExternalFaces::DoExecute(const vtkm::cont::DataSet& input)
// New Filter Design: we generate new output and map the fields first.
auto output = this->GenerateOutput(input, outCellSet);
auto mapper = [&, this](auto& result, const auto& f) {
// New Design: We are still using the old MapFieldOntoOutput to demonstrate the transition
this->MapFieldOntoOutput(result, f);
};
this->MapFieldsOntoOutput(input, output, mapper);
// New Filter Design: then we remove entities if requested.
if (this->CompactPoints)

@ -107,14 +107,8 @@ vtkm::cont::DataSet ExtractGeometry::DoExecute(const vtkm::cont::DataSet& input)
cells.CastAndCallForTypes<VTKM_DEFAULT_CELL_SET_LIST>(worker);
// create the output dataset
vtkm::cont::DataSet output;
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
output.SetCellSet(outCells);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
this->MapFieldsOntoOutput(input, output, mapper);
return output;
return this->CreateResult(input, outCells, input.GetCoordinateSystems(), mapper);
}
} // namespace entity_extraction

@ -59,12 +59,9 @@ vtkm::cont::DataSet ExtractPoints::DoExecute(const vtkm::cont::DataSet& input)
outCellSet = worklet.Run(cells, coords.GetData(), this->Function, this->ExtractInside);
// create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); };
this->MapFieldsOntoOutput(input, output, mapper);
vtkm::cont::DataSet output =
this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper);
// compact the unused points in the output dataset
if (this->CompactPoints)

@ -62,10 +62,6 @@ vtkm::cont::DataSet ExtractStructured::DoExecute(const vtkm::cont::DataSet& inpu
auto coords = worklet.MapCoordinates(coordinates);
vtkm::cont::CoordinateSystem outputCoordinates(coordinates.GetName(), coords);
vtkm::cont::DataSet output;
output.SetCellSet(vtkm::cont::UnknownCellSet(cellset));
output.AddCoordinateSystem(outputCoordinates);
// Create map arrays for mapping fields. Could potentially save some time to first check to see
// if these arrays would be used.
auto CellFieldMap =
@ -76,9 +72,7 @@ vtkm::cont::DataSet ExtractStructured::DoExecute(const vtkm::cont::DataSet& inpu
auto mapper = [&](auto& result, const auto& f) {
DoMapField(result, f, CellFieldMap, PointFieldMap);
};
this->MapFieldsOntoOutput(input, output, mapper);
return output;
return this->CreateResult(input, cellset, outputCoordinates, mapper);
}
} // namespace entity_extraction

@ -368,14 +368,8 @@ VTKM_CONT vtkm::cont::DataSet GhostCellRemove::DoExecute(const vtkm::cont::DataS
throw vtkm::cont::ErrorFilterExecution("Unsupported ghost cell removal type");
}
vtkm::cont::DataSet output;
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
output.SetCellSet(cellOut);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
this->MapFieldsOntoOutput(input, output, mapper);
return output;
return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper);
}
}

@ -70,14 +70,8 @@ VTKM_CONT vtkm::cont::DataSet Mask::DoExecute(const vtkm::cont::DataSet& input)
cells.CastAndCallForTypes<VTKM_DEFAULT_CELL_SET_LIST>(workletCaller);
// create the output dataset
vtkm::cont::DataSet output;
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
output.SetCellSet(cellOut);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
this->MapFieldsOntoOutput(input, output, mapper);
return output;
return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper);
}
} // namespace entity_extraction
} // namespace filter

@ -55,12 +55,9 @@ VTKM_CONT vtkm::cont::DataSet MaskPoints::DoExecute(const vtkm::cont::DataSet& i
outCellSet = worklet.Run(cells, this->Stride);
// create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); };
this->MapFieldsOntoOutput(input, output, mapper);
vtkm::cont::DataSet output =
this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper);
// compact the unused points in the output dataset
if (this->CompactPoints)

@ -98,14 +98,8 @@ vtkm::cont::DataSet Threshold::DoExecute(const vtkm::cont::DataSet& input)
fieldArray.CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
ResolveArrayType);
vtkm::cont::DataSet output;
output.SetCellSet(cellOut);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
this->MapFieldsOntoOutput(input, output, mapper);
return output;
return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper);
}
} // namespace entity_extraction
} // namespace filter

@ -173,12 +173,9 @@ VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(const vtkm::cont::DataS
this->CastAndCallScalarField(field, resolveType);
// create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); };
this->MapFieldsOntoOutput(input, output, mapper);
vtkm::cont::DataSet output =
this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper);
// compact the unused points in the output dataset
if (this->CompactPoints)

@ -43,7 +43,7 @@ namespace field_transform
{
vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input)
{
vtkm::cont::DataSet output = input;
vtkm::cont::DataSet output = this->CreateResult(input);
if (this->GetGeneratePointIds())
{
@ -56,8 +56,6 @@ vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input)
output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells()));
}
this->MapFieldsOntoOutput(input, output);
return output;
}
} // namespace field_transform

@ -77,13 +77,8 @@ VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(const vtkm::cont::DataSet&
this->CastAndCallVecField<3>(primaryArray, resolveType);
vtkm::cont::DataSet outDataSet;
outDataSet.CopyStructure(inDataSet);
outDataSet.AddField({ this->GetOutputFieldName(), primaryField.GetAssociation(), outArray });
this->MapFieldsOntoOutput(inDataSet, outDataSet);
return outDataSet;
return this->CreateResultField(
inDataSet, this->GetOutputFieldName(), primaryField.GetAssociation(), outArray);
}
}

@ -108,15 +108,10 @@ VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& i
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::FloatDefault>(), secondaryField);
}
vtkm::cont::DataSet outDataSet;
outDataSet.CopyStructure(inDataSet);
outDataSet.AddField({ this->GetOutputFieldName(),
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
outArray });
this->MapFieldsOntoOutput(inDataSet, outDataSet);
return outDataSet;
return this->CreateResultField(inDataSet,
this->GetOutputFieldName(),
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
outArray);
}
} // namespace vector_calculus