Commit de4e840e authored by Utkarsh Ayachit's avatar Utkarsh Ayachit
Browse files

enhance filter API

Filters now support executing on a dataset to produce a result dataset
with automatic mapping of fields to the output dataset. Fields to map
can be selected using `vtkm::filter::FieldSelection` class, which provides
constructors to map all or no fields, along with a selection of fields.

This updates all tests to use the new filter API.
parent c255c0eb
......@@ -32,6 +32,8 @@ set(headers
ExtractPoints.h
ExtractStructured.h
FieldMetadata.h
FieldSelection.h
Filter.h
FilterCell.h
FilterDataSet.h
FilterDataSetWithField.h
......@@ -73,6 +75,7 @@ set(header_template_sources
ExtractGeometry.hxx
ExtractPoints.hxx
ExtractStructured.hxx
Filter.hxx
FilterCell.hxx
FilterDataSet.hxx
FilterDataSetWithField.hxx
......
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_filter_FieldSelection_h
#define vtk_m_filter_FieldSelection_h
#include <initializer_list>
#include <set>
#include <vtkm/cont/Field.h>
namespace vtkm
{
namespace filter
{
/// A \c FieldSelection stores information about fields to map for input dataset to output
/// when a filter is executed. A \c FieldSelection object is passed to
/// `vtkm::filter::Filter::Execute` to execute the filter and map selected
/// fields. It is possible to easily construct \c FieldSelection that selects all or
/// none of the input fields.
class FieldSelection
{
public:
enum ModeEnum
{
MODE_SELECTED,
MODE_ALL
};
VTKM_CONT
FieldSelection(ModeEnum mode = MODE_SELECTED)
: Mode(mode)
{
}
/// Use this constructor create a field selection given the field names e.g.
/// `FieldSelection({"field_one", "field_two"})`.
VTKM_CONT
FieldSelection(std::initializer_list<std::string> fields)
: Mode(MODE_SELECTED)
{
for (const std::string& afield : fields)
{
this->AddField(afield, vtkm::cont::Field::ASSOC_ANY);
}
}
/// Use this constructor create a field selection given the field names and
/// associations e.g.
/// @code{cpp}
/// FieldSelection({
/// {"field_one", vtkm::cont::Field::ASSOC_POINTS},
/// {"field_two", vtkm::cont::Field::ASSOC_CELL_SET} });
/// @endcode
VTKM_CONT
FieldSelection(
std::initializer_list<std::pair<std::string, vtkm::cont::Field::AssociationEnum>> fields)
: Mode(MODE_SELECTED)
{
for (const auto& item : fields)
{
this->AddField(item.first, item.second);
}
}
VTKM_CONT
~FieldSelection() {}
/// Returns true if the input field should be mapped to the output
/// dataset.
VTKM_CONT
bool IsFieldSelected(const vtkm::cont::Field& inputField) const
{
return this->IsFieldSelected(inputField.GetName(), inputField.GetAssociation());
}
bool IsFieldSelected(
const std::string& name,
vtkm::cont::Field::AssociationEnum association = vtkm::cont::Field::ASSOC_ANY) const
{
switch (this->Mode)
{
case MODE_ALL:
return true;
case MODE_SELECTED:
default:
if (this->Fields.find(Field(name, association)) != this->Fields.end())
{
return true;
}
// if not exact match, let's lookup for ASSOC_ANY.
for (const auto& aField : this->Fields)
{
if (aField.Name == name)
{
if (aField.Association == vtkm::cont::Field::ASSOC_ANY ||
association == vtkm::cont::Field::ASSOC_ANY)
{
return true;
}
}
}
return false;
}
}
//@{
/// Add fields to map. Note, if Mode is not MODE_SELECTED, then adding fields
/// will have no impact of the fields that will be mapped.
VTKM_CONT
void AddField(const vtkm::cont::Field& inputField)
{
this->AddField(inputField.GetName(), inputField.GetAssociation());
}
VTKM_CONT
void AddField(const std::string& fieldName,
vtkm::cont::Field::AssociationEnum association = vtkm::cont::Field::ASSOC_ANY)
{
this->Fields.insert(Field(fieldName, association));
}
//@}
/// Clear all fields added using `AddField`.
VTKM_CONT
void ClearFields() { this->Fields.clear(); }
VTKM_CONT
ModeEnum GetMode() const { return this->Mode; }
void SetMode(ModeEnum val) { this->Mode = val; }
private:
ModeEnum Mode; ///< mode
struct Field
{
std::string Name;
vtkm::cont::Field::AssociationEnum Association;
Field() = default;
Field(const std::string& name, vtkm::cont::Field::AssociationEnum assoc)
: Name(name)
, Association(assoc)
{
}
Field& operator=(const Field&) = default;
bool operator<(const Field& other) const
{
return (this->Association == other.Association) ? (this->Name < other.Name)
: (this->Association < other.Association);
}
};
std::set<Field> Fields;
};
}
}
#endif // vtk_m_filter_FieldSelection_h
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_filter_Filter_h
#define vtk_m_filter_Filter_h
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/filter/FieldSelection.h>
#include <vtkm/filter/PolicyBase.h>
namespace vtkm
{
namespace filter
{
template <typename Derived>
class Filter
{
public:
VTKM_CONT
Filter();
VTKM_CONT
~Filter();
VTKM_CONT
void SetRuntimeDeviceTracker(const vtkm::cont::RuntimeDeviceTracker& tracker)
{
this->Tracker = tracker;
}
VTKM_CONT
const vtkm::cont::RuntimeDeviceTracker& GetRuntimeDeviceTracker() const { return this->Tracker; }
VTKM_CONT
vtkm::cont::RuntimeDeviceTracker& GetRuntimeDeviceTracker() { return this->Tracker; }
//@{
/// Executes the filter on the input and producer an result dataset.
/// FieldSelection can be specified to indicate which fields should be passed
/// on from the input to the output.
///
/// On success, this the dataset produced. On error, vtkm::cont::ErrorExecution will be thrown.
VTKM_CONT
vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input,
const FieldSelection& fieldSelection = FieldSelection());
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const FieldSelection& fieldSelection = FieldSelection());
//@}
//@{
/// MultiBlock variants of execute.
VTKM_CONT
vtkm::cont::MultiBlock Execute(const vtkm::cont::MultiBlock& input,
const FieldSelection& fieldSelection = FieldSelection());
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::MultiBlock Execute(const vtkm::cont::MultiBlock& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const FieldSelection& fieldSelection = FieldSelection());
//@}
private:
vtkm::cont::RuntimeDeviceTracker Tracker;
};
}
} // namespace vtkm::filter
#include <vtkm/filter/Filter.hxx>
#endif
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/filter/FieldMetadata.h>
#include <vtkm/filter/FilterTraits.h>
#include <vtkm/filter/PolicyDefault.h>
#include <vtkm/filter/Result.h>
#include <vtkm/filter/internal/ResolveFieldTypeAndExecute.h>
#include <vtkm/filter/internal/ResolveFieldTypeAndMap.h>
#include <vtkm/cont/Error.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
namespace vtkm
{
namespace filter
{
//----------------------------------------------------------------------------
template <typename Derived>
inline VTKM_CONT Filter<Derived>::Filter()
: Tracker(vtkm::cont::GetGlobalRuntimeDeviceTracker())
{
}
//----------------------------------------------------------------------------
template <typename Derived>
inline VTKM_CONT Filter<Derived>::~Filter()
{
}
//----------------------------------------------------------------------------
template <typename Derived>
inline VTKM_CONT vtkm::cont::DataSet Filter<Derived>::Execute(const vtkm::cont::DataSet& input,
const FieldSelection& fieldSelection)
{
return this->Execute(input, vtkm::filter::PolicyDefault(), fieldSelection);
}
//----------------------------------------------------------------------------
template <typename Derived>
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet Filter<Derived>::Execute(
const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const FieldSelection& fieldSelection)
{
Derived* self = static_cast<Derived*>(this);
//self->DoPreExecute(input, policy, fieldSelection);
Result result = self->PrepareForExecution(input, policy);
//self->DoPostExecute(result.GetDataSet(), input, policy);
if (!result.IsValid())
{
throw vtkm::cont::ErrorExecution("Failed to execute filter.");
}
for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc)
{
auto field = input.GetField(cc);
if (fieldSelection.IsFieldSelected(field))
{
self->MapFieldOntoOutput(result, field, policy);
}
}
return result.GetDataSet();
}
//----------------------------------------------------------------------------
template <typename Derived>
inline VTKM_CONT vtkm::cont::MultiBlock Filter<Derived>::Execute(
const vtkm::cont::MultiBlock& input,
const FieldSelection& fieldSelection)
{
return this->Execute(input, vtkm::filter::PolicyDefault(), fieldSelection);
}
//----------------------------------------------------------------------------
template <typename Derived>
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::MultiBlock Filter<Derived>::Execute(
const vtkm::cont::MultiBlock& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const FieldSelection& fieldSelection)
{
// Derived* self = static_cast<Derived*>(this);
//self->DoPreExecute(input, policy, fieldSelection);
vtkm::cont::MultiBlock output;
for (auto& inDataSet : input)
{
vtkm::cont::DataSet outDataSet = this->Execute(inDataSet, policy, fieldSelection);
output.AddBlock(outDataSet);
}
//self->DoPreExecute(output, input, policy);
return output;
}
}
}
......@@ -25,8 +25,10 @@
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/filter/Filter.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/Result.h>
......@@ -36,7 +38,7 @@ namespace filter
{
template <class Derived>
class FilterDataSet
class FilterDataSet : public vtkm::filter::Filter<FilterDataSet<Derived>>
{
public:
VTKM_CONT
......@@ -57,22 +59,6 @@ public:
VTKM_CONT
vtkm::Id GetActiveCoordinateSystemIndex() const { return this->CoordinateSystemIndex; }
VTKM_CONT
void SetRuntimeDeviceTracker(const vtkm::cont::RuntimeDeviceTracker& tracker)
{
this->Tracker = tracker;
}
VTKM_CONT
const vtkm::cont::RuntimeDeviceTracker& GetRuntimeDeviceTracker() const { return this->Tracker; }
VTKM_CONT
Result Execute(const vtkm::cont::DataSet& input);
template <typename DerivedPolicy>
VTKM_CONT Result Execute(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
//From the field we can extract the association component
// ASSOC_ANY -> unable to map
// ASSOC_WHOLE_MESH -> (I think this is points)
......@@ -92,10 +78,10 @@ private:
VTKM_CONT Result PrepareForExecution(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
std::string OutputFieldName;
vtkm::Id CellSetIndex;
vtkm::Id CoordinateSystemIndex;
vtkm::cont::RuntimeDeviceTracker Tracker;
friend class vtkm::filter::Filter<FilterDataSet<Derived>>;
};
}
} // namespace vtkm::filter
......
......@@ -38,36 +38,17 @@ namespace filter
{
//----------------------------------------------------------------------------
template <class Derived>
template <typename Derived>
inline VTKM_CONT FilterDataSet<Derived>::FilterDataSet()
: OutputFieldName()
, CellSetIndex(0)
: CellSetIndex(0)
, CoordinateSystemIndex(0)
, Tracker(vtkm::cont::GetGlobalRuntimeDeviceTracker())
{
}
//----------------------------------------------------------------------------
template <class Derived>
inline VTKM_CONT FilterDataSet<Derived>::~FilterDataSet()
{
}
//-----------------------------------------------------------------------------
template <typename Derived>
inline VTKM_CONT Result FilterDataSet<Derived>::Execute(const vtkm::cont::DataSet& input)
{
return this->Execute(input, vtkm::filter::PolicyDefault());
}
//-----------------------------------------------------------------------------
template <typename Derived>
template <typename DerivedPolicy>
inline VTKM_CONT Result
FilterDataSet<Derived>::Execute(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
inline VTKM_CONT FilterDataSet<Derived>::~FilterDataSet()
{
return this->PrepareForExecution(input, policy);
}
//-----------------------------------------------------------------------------
......@@ -113,7 +94,8 @@ FilterDataSet<Derived>::PrepareForExecution(const vtkm::cont::DataSet& input,
detail::FilterDataSetPrepareForExecutionFunctor<Derived, DerivedPolicy> functor(
static_cast<Derived*>(this), input, policy);
vtkm::cont::TryExecute(functor, this->Tracker, typename DerivedPolicy::DeviceAdapterList());
vtkm::cont::TryExecute(
functor, this->GetRuntimeDeviceTracker(), typename DerivedPolicy::DeviceAdapterList());
return functor.Result;
}
......@@ -143,7 +125,7 @@ inline VTKM_CONT bool FilterDataSet<Derived>::MapFieldOntoOutput(
using Traits = vtkm::filter::FilterTraits<Derived>;
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->GetRuntimeDeviceTracker());
}
//the bool valid will be modified by the map algorithm to hold if the
......
......@@ -28,6 +28,7 @@
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/filter/Filter.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/Result.h>
......@@ -37,7 +38,7 @@ namespace filter
{
template <class Derived>
class FilterDataSetWithField
class FilterDataSetWithField : public vtkm::filter::Filter<FilterDataSetWithField<Derived>>
{
public:
VTKM_CONT
......@@ -58,48 +59,32 @@ public:
VTKM_CONT
vtkm::Id GetActiveCoordinateSystemIndex() const { return this->CoordinateSystemIndex; }
//@{
/// Choose the field to operate on. Note, if
/// `this->UseCoordinateSystemAsField` is true, then the active field is not used.
VTKM_CONT
void SetRuntimeDeviceTracker(const vtkm::cont::RuntimeDeviceTracker& tracker)
void SetActiveField(const std::string& name,
vtkm::cont::Field::AssociationEnum association = vtkm::cont::Field::ASSOC_ANY)
{
this->Tracker = tracker;
this->ActiveFieldName = name;
this->ActiveFieldAssociation = association;
}
VTKM_CONT
const vtkm::cont::RuntimeDeviceTracker& GetRuntimeDeviceTracker() const { return this->Tracker; }
VTKM_CONT
Result Execute(const vtkm::cont::DataSet& input, const std::string& inFieldName);
VTKM_CONT
Result Execute(const vtkm::cont::DataSet& input, const vtkm::cont::Field& field);
VTKM_CONT const std::string& GetActiveFieldName() const { return this->ActiveFieldName; }
VTKM_CONT vtkm::cont::Field::AssociationEnum GetActiveFieldAssociation() const
{
return this->ActiveFieldAssociation;
}
//@}
//@{
/// To simply use the active coordinate system as the field to operate on, set
/// UseCoordinateSystemAsField to true.
VTKM_CONT
Result Execute(const vtkm::cont::DataSet& input, const vtkm::cont::CoordinateSystem& field);
void SetUseCoordinateSystemAsField(bool val) { this->UseCoordinateSystemAsField = val; }
VTKM_CONT
std::vector<vtkm::filter::Result> Execute(const vtkm::cont::MultiBlock& input,
const std::string& inFieldName);
template <typename DerivedPolicy>
VTKM_CONT std::vector<vtkm::filter::Result> Execute(
const vtkm::cont::MultiBlock& input,
const std::string& inFieldName,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename DerivedPolicy>
VTKM_CONT Result Execute(const vtkm::cont::DataSet& input,
const std::string& inFieldName,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename DerivedPolicy>
VTKM_CONT Result Execute(const vtkm::cont::DataSet& input,
const vtkm::cont::Field& field,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename DerivedPolicy>
VTKM_CONT Result Execute(const vtkm::cont::DataSet& input,
const vtkm::cont::CoordinateSystem& field,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
bool GetUseCoordinateSystemAsField() const { return this->UseCoordinateSystemAsField; }
//@}
//From the field we can extract the association component
// ASSOC_ANY -> unable to map
......@@ -116,6 +101,10 @@ public:
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
private:
template <typename DerivedPolicy>
VTKM_CONT Result PrepareForExecution(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);