2.6. Running Filters

Filters are functional units that take data as input and write new data as output. Filters operate on viskores::cont::DataSet objects, which are described in Chapter 2.4 (Data Sets).

Did You Know?

The structure of filters in Viskores is significantly simpler than their counterparts in VTK. VTK filters are arranged in a dataflow network (a.k.a. a visualization pipeline) and execution management is handled automatically. In contrast, Viskores filters are simple imperative units, which are simply called with input data and return output data.

Viskores comes with several filters ready for use. This chapter gives an overview of how to run the filters. Chapter 2.7 (Provided Filters) describes the common filters provided by Viskores. Later, Part 3 (Developing Algorithms) describes the necessary steps in creating new filters in Viskores.

2.6.1. Basic Filter Operation

Different filters will be used in different ways, but the basic operation of all filters is to instantiate the filter class, set the state parameters on the filter object, and then call the filter’s viskores::filter::Filter::Execute() method. It takes a viskores::cont::DataSet and returns a new viskores::cont::DataSet, which contains the modified data.

viskores::cont::DataSet viskores::filter::Filter::Execute(const viskores::cont::DataSet &input)

Executes the filter on the input and produces a result dataset.

On success, this the dataset produced. On error, viskores::cont::ErrorExecution will be thrown.

The viskores::filter::Filter::Execute() method can alternately take a viskores::cont::PartitionedDataSet object, which is a composite of viskores::cont::DataSet objects. In this case viskores::filter::Filter::Execute() will return another viskores::cont::PartitionedDataSet object.

viskores::cont::PartitionedDataSet viskores::filter::Filter::Execute(const viskores::cont::PartitionedDataSet &input)

Executes the filter on the input PartitionedDataSet and produces a result PartitionedDataSet.

On success, this the dataset produced. On error, viskores::cont::ErrorExecution will be thrown.

The following example provides a simple demonstration of using a filter. It specifically uses the point elevation filter to estimate the air pressure at each point based on its elevation.

Example 2.24 Using viskores::filter::field_transform::PointElevation to estiate air pressure.
 1VISKORES_CONT
 2viskores::cont::DataSet ComputeAirPressure(viskores::cont::DataSet dataSet)
 3{
 4  viskores::filter::field_transform::PointElevation elevationFilter;
 5
 6  // Use the elevation filter to estimate atmospheric pressure based on the
 7  // height of the point coordinates. Atmospheric pressure is 101325 Pa at
 8  // sea level and drops about 12 Pa per meter.
 9  elevationFilter.SetLowPoint(0.0, 0.0, 0.0);
10  elevationFilter.SetHighPoint(0.0, 0.0, 2000.0);
11  elevationFilter.SetRange(101325.0, 77325.0);
12
13  elevationFilter.SetUseCoordinateSystemAsField(true);
14
15  elevationFilter.SetOutputFieldName("pressure");
16
17  viskores::cont::DataSet result = elevationFilter.Execute(dataSet);
18
19  return result;
20}

We see that this example follows the previously described procedure of constructing the filter (line 4), setting the state parameters (lines 9 – 15), and finally executing the filter on a viskores::cont::DataSet (line 17).

Every viskores::cont::DataSet object contains a list of fields, which describe some numerical value associated with different parts of the data set in space. Fields often represent physical properties such as temperature, pressure, or velocity. Fields are identified with string names. There are also special fields called coordinate systems that describe the location of points in space. Field are mentioned here because they are often used as input data to the filter’s operation and filters often generate new fields in the output. This is the case in Example 2.24. In line 13 the coordinate system is set as the input field and in line 15 the name to use for the generated output field is selected.

2.6.2. Advanced Field Management

Most filters work with fields as inputs and outputs to their algorithms. Although in the previous discussions of the filters we have seen examples of specifying fields, these examples have been kept brief in the interest of clarity. In this section we revisit how filters manage fields and provide more detailed documentation of the controls.

Note that not all of the discussion in this section applies to all the filters provided by Viskores. For example, not all filters have a specified input field. But where possible, the interface to the filter objects is kept consistent.

2.6.2.1. Input Fields

Filters that take one or more fields as input have a common set of methods to set the “active” fields to operate on. They might also have custom methods to ease setting the appropriate fields, but these are the base methods.

inline void viskores::filter::Filter::SetActiveField(const std::string &name, viskores::cont::Field::Association association = viskores::cont::Field::Association::Any)

Specifies a field to operate on.

The number of input fields (or whether the filter operates on input fields at all) is specific to each particular filter.

inline void viskores::filter::Filter::SetActiveField(viskores::IdComponent index, const std::string &name, viskores::cont::Field::Association association = viskores::cont::Field::Association::Any)

Specifies a field to operate on.

The number of input fields (or whether the filter operates on input fields at all) is specific to each particular filter.

inline const std::string &viskores::filter::Filter::GetActiveFieldName(viskores::IdComponent index = 0) const

Specifies a field to operate on.

The number of input fields (or whether the filter operates on input fields at all) is specific to each particular filter.

inline viskores::cont::Field::Association viskores::filter::Filter::GetActiveFieldAssociation(viskores::IdComponent index = 0) const

Specifies a field to operate on.

The number of input fields (or whether the filter operates on input fields at all) is specific to each particular filter.

inline void viskores::filter::Filter::SetActiveCoordinateSystem(viskores::Id coord_idx)

Specifies the coordinate system index to make active to use when processing the input viskores::cont::DataSet.

This is used primarily by the Filter to select the coordinate system to use as a field when UseCoordinateSystemAsField is true.

inline void viskores::filter::Filter::SetActiveCoordinateSystem(viskores::IdComponent index, viskores::Id coord_idx)

Specifies the coordinate system index to make active to use when processing the input viskores::cont::DataSet.

This is used primarily by the Filter to select the coordinate system to use as a field when UseCoordinateSystemAsField is true.

inline viskores::Id viskores::filter::Filter::GetActiveCoordinateSystemIndex(viskores::IdComponent index = 0) const

Specifies the coordinate system index to make active to use when processing the input viskores::cont::DataSet.

This is used primarily by the Filter to select the coordinate system to use as a field when UseCoordinateSystemAsField is true.

inline void viskores::filter::Filter::SetUseCoordinateSystemAsField(bool val)

Specifies whether to use point coordinates as the input field.

When true, the values for the active field are ignored and the active coordinate system is used instead.

inline void viskores::filter::Filter::SetUseCoordinateSystemAsField(viskores::IdComponent index, bool val)

Specifies whether to use point coordinates as the input field.

When true, the values for the active field are ignored and the active coordinate system is used instead.

inline bool viskores::filter::Filter::GetUseCoordinateSystemAsField(viskores::IdComponent index = 0) const

Specifies whether to use point coordinates as the input field.

When true, the values for the active field are ignored and the active coordinate system is used instead.

inline viskores::IdComponent viskores::filter::Filter::GetNumberOfActiveFields() const

Return the number of active fields currently set.

The general interface to Filter allows a user to set an arbitrary number of active fields (indexed 0 and on). This method returns the number of active fields that are set. Note that the filter implementation is free to ignore any active fields it does not support. Also note that an active field can be set to be either a named field or a coordinate system.

The viskores::filter::Filter::SetActiveField() method takes an optional argument that specifies which topological elements the field is associated with (such as points or cells). The viskores::cont::Field::Association enumeration is used to select the field association.

Example 2.25 Setting a field’s active filter with an association.
1  filter.SetActiveField("pointvar", viskores::cont::Field::Association::Points);

Common Errors

It is possible to have two fields with the same name that are only differentiable by the association. That is, you could have a point field and a cell field with different data but the same name. Thus, it is best practice to specify the field association when possible. Likewise, it is poor practice to have two fields with the same name, particularly if the data are not equivalent in some way. It is often the case that fields are selected without an association.

It is also possible to set the active scalar field as a coordinate system of the data. A coordinate system essentially provides the spatial location of the points of the data and they have a special place in the viskores::cont::DataSet structure. (See Section 2.4.4 (Coordinate Systems) for details on coordinate systems.) You can use a coordinate system as the active scalars by calling the viskores::filter::Filter::SetUseCoordinateSystemAsField() method with a true flag. Since a viskores::cont::DataSet can have multiple coordinate systems, you can select the desired coordinate system with viskores::filter::Filter::SetActiveCoordinateSystem(). (By default, the first coordinate system, index 0, will be used.)

Example 2.26 Setting the active coordinate system.
1  filter.SetUseCoordinateSystemAsField(true);
2  filter.SetActiveCoordinateSystem(1);

2.6.2.2. Passing Fields from Input to Output

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. By default, the filter will automatically pass all fields from input to output (performing whatever transformations are necessary). You can control which fields are passed (and equivalently which are not) with the viskores::filter::Filter::SetFieldsToPass() methods.

void viskores::filter::Filter::SetFieldsToPass(viskores::filter::FieldSelection &&fieldsToPass)

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

inline const viskores::filter::FieldSelection &viskores::filter::Filter::GetFieldsToPass() const

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

inline viskores::filter::FieldSelection &viskores::filter::Filter::GetFieldsToPass()

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

There are multiple ways to to use viskores::filter::Filter::SetFieldsToPass() to control what fields are passed. If you want to turn off all fields so that none are passed, call viskores::filter::Filter::SetFieldsToPass() with viskores::filter::FieldSelection::Mode::None.

Example 2.27 Turning off the passing of all fields when executing a filter.
1    filter.SetFieldsToPass(viskores::filter::FieldSelection::Mode::None);

If you want to pass one specific field, you can pass that field’s name to viskores::filter::Filter::SetFieldsToPass().

inline void viskores::filter::Filter::SetFieldsToPass(const std::string &fieldname, viskores::filter::FieldSelection::Mode mode)

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

void viskores::filter::Filter::SetFieldsToPass(const std::string &fieldname, viskores::cont::Field::Association association, viskores::filter::FieldSelection::Mode mode = viskores::filter::FieldSelection::Mode::Select)

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

Example 2.28 Setting one field to pass by name.
1    filter.SetFieldsToPass("pointvar");

Or you can provide a list of fields to pass by giving viskores::filter::Filter::SetFieldsToPass() an initializer list of names.

void viskores::filter::Filter::SetFieldsToPass(std::initializer_list<std::string> fields, viskores::filter::FieldSelection::Mode mode = viskores::filter::FieldSelection::Mode::Select)

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

Example 2.29 Using a list of fields for a filter to pass.
1    filter.SetFieldsToPass({ "pointvar", "cellvar" });

If you want to instead select a list of fields to not pass, you can add viskores::filter::FieldSelection::Mode::Exclude as an argument to viskores::filter::Filter::SetFieldsToPass().

Example 2.30 Excluding a list of fields for a filter to pass.
1    filter.SetFieldsToPass({ "pointvar", "cellvar" },
2                           viskores::filter::FieldSelection::Mode::Exclude);

Ultimately, viskores::filter::Filter::SetFieldsToPass() takes a viskores::filter::FieldSelection object. You can create one directly to select (or exclude) specific fields and their associations.

class FieldSelection

A FieldSelection stores information about fields to map for input dataset to output when a filter is executed.

A FieldSelection object is passed to viskores::filter::Filter::Execute to execute the filter and map selected fields. It is possible to easily construct FieldSelection that selects all or none of the input fields.

Unnamed Group

inline void AddField(const viskores::cont::Field &inputField)

Add fields to select or exclude. If no mode is specified, then the mode will follow that of GetMode().

inline void AddField(const viskores::cont::Field &inputField, Mode mode)

Add fields to select or exclude. If no mode is specified, then the mode will follow that of GetMode().

inline void AddField(const std::string &fieldName, viskores::cont::Field::Association association = viskores::cont::Field::Association::Any)

Add fields to select or exclude. If no mode is specified, then the mode will follow that of GetMode().

inline void AddField(const std::string &fieldName, Mode mode)

Add fields to select or exclude. If no mode is specified, then the mode will follow that of GetMode().

void AddField(const std::string &fieldName, viskores::cont::Field::Association association, Mode mode)

Add fields to select or exclude. If no mode is specified, then the mode will follow that of GetMode().

Unnamed Group

inline Mode GetFieldMode(const viskores::cont::Field &inputField) const

Returns the mode for a particular field. If the field as been added with AddField (or another means), then this will return Select or Exclude. If the field has not been added, None will be returned.

Mode GetFieldMode(const std::string &fieldName, viskores::cont::Field::Association association = viskores::cont::Field::Association::Any) const

Returns the mode for a particular field. If the field as been added with AddField (or another means), then this will return Select or Exclude. If the field has not been added, None will be returned.

Public Functions

FieldSelection(const std::string &field, Mode mode = Mode::Select)

Use this constructor to create a field selection given a single field name.

FieldSelection("field_name");
FieldSelection(const char *field, Mode mode = Mode::Select)

Use this constructor to create a field selection given a single field name.

FieldSelection("field_name");
FieldSelection(const std::string &field, viskores::cont::Field::Association association, Mode mode = Mode::Select)

Use this constructor to create a field selection given a single name and association.

FieldSelection("field_name", viskores::cont::Field::Association::Points)
{cpp}

FieldSelection(std::initializer_list<std::string> fields, Mode mode = Mode::Select)

Use this constructor to create a field selection given the field names.

FieldSelection({"field_one", "field_two"});
FieldSelection(std::initializer_list<std::pair<std::string, viskores::cont::Field::Association>> fields, Mode mode = Mode::Select)

Use this constructor create a field selection given the field names and associations e.g.

using pair_type = std::pair<std::string, viskores::cont::Field::Association>;
FieldSelection({
     pair_type{"field_one", viskores::cont::Field::Association::Points},
     pair_type{"field_two", viskores::cont::Field::Association::Cells} });
FieldSelection(std::initializer_list<viskores::Pair<std::string, viskores::cont::Field::Association>> fields, Mode mode = Mode::Select)

Use this constructor create a field selection given the field names and associations e.g.

using pair_type = viskores::Pair<std::string, viskores::cont::Field::Association>;
FieldSelection({
     pair_type{"field_one", viskores::cont::Field::Association::Points},
     pair_type{"field_two", viskores::cont::Field::Association::Cells} });
inline bool IsFieldSelected(const viskores::cont::Field &inputField) const

Returns true if the input field should be mapped to the output dataset.

inline bool HasField(const viskores::cont::Field &inputField) const

Returns true if the input field has been added to this selection.

Note that depending on the mode of this selection, the result of HasField is not necessarily the same as IsFieldSelected. (If the mode is MODE_SELECT, then the result of the two will be the same.)

void ClearFields()

Clear all fields added using AddField.

Mode GetMode() const

Gets the mode of the field selection.

If Select mode is on, then only fields that have a Select mode are considered as selected. (All others are considered unselected.) Calling AddField in this mode will mark it as Select. If Exclude mode is on, then all fields are considered selected except those fields with an Exclude mode. Calling AddField in this mode will mark it as Exclude.

void SetMode(Mode val)

Sets the mode of the field selection.

If Select mode is on, then only fields that have a Select mode are considered as selected. (All others are considered unselected.) Calling AddField in this mode will mark it as Select. If Exclude mode is on, then all fields are considered selected except those fields with an Exclude mode. Calling AddField in this mode will mark it as Exclude.

If the mode is set to None, then the field modes are cleared and the overall mode is set to Select (meaning none of the fields are initially selected). If the mode is set to All, then the field modes are cleared and the overall mode is set to Exclude (meaning all of the fields are initially selected).

Example 2.31 Using viskores::filter::FieldSelection to select cells to pass.
1    viskores::filter::FieldSelection fieldSelection;
2    fieldSelection.AddField("scalars");
3    fieldSelection.AddField("cellvar", viskores::cont::Field::Association::Cells);
4
5    filter.SetFieldsToPass(fieldSelection);

It is also possible to specify field attributions directly to viskores::filter::Filter::SetFieldsToPass(). If you only have one field, you can just specify both the name and attribution. If you have multiple fields, you can provide an initializer list of std::pair or viskores::Pair containing a std::string and a viskores::cont::Field::Association. In either case, you can add an optional last argument of viskores::filter::FieldSelection::Mode::Exclude to exclude the specified filters instead of selecting them.

void viskores::filter::Filter::SetFieldsToPass(std::initializer_list<std::pair<std::string, viskores::cont::Field::Association>> fields, viskores::filter::FieldSelection::Mode mode = viskores::filter::FieldSelection::Mode::Select)

Specify which fields get passed from input to output.

After a filter successfully executes and returns a new data set, fields are mapped from input to output. Depending on what operation the filter does, this could be a simple shallow copy of an array, or it could be a computed operation. You can control which fields are passed (and equivalently which are not) with this parameter.

By default, all fields are passed during execution.

Example 2.32 Selecting one field and its association for a filter to pass.
1    filter.SetFieldsToPass("pointvar", viskores::cont::Field::Association::Points);
Example 2.33 Selecting a list of fields and their associations for a filter to pass.
1    filter.SetFieldsToPass(
2      { viskores::make_Pair("pointvar", viskores::cont::Field::Association::Points),
3        viskores::make_Pair("cellvar", viskores::cont::Field::Association::Cells),
4        viskores::make_Pair("scalars", viskores::cont::Field::Association::Any) });

Note that coordinate systems in a viskores::cont::DataSet are simply links to point fields, and by default filters will pass coordinate systems regardless of the field selection flags. To prevent a filter from passing a coordinate system if its associated field is not selected, use the viskores::filter::Filter::SetPassCoordinateSystems() method.

inline void viskores::filter::Filter::SetPassCoordinateSystems(bool flag)

Specify whether to always pass coordinate systems.

viskores::cont::CoordinateSystems in a DataSet are really just point fields marked as being a coordinate system. Thus, a coordinate system is passed if and only if the associated field is passed.

By default, the filter will pass all fields associated with a coordinate system regardless of the FieldsToPass marks the field as passing. If this option is set to false, then coordinate systems will only be passed if it is marked so by FieldsToPass.

inline bool viskores::filter::Filter::GetPassCoordinateSystems() const

Specify whether to always pass coordinate systems.

viskores::cont::CoordinateSystems in a DataSet are really just point fields marked as being a coordinate system. Thus, a coordinate system is passed if and only if the associated field is passed.

By default, the filter will pass all fields associated with a coordinate system regardless of the FieldsToPass marks the field as passing. If this option is set to false, then coordinate systems will only be passed if it is marked so by FieldsToPass.

Example 2.34 Turning off the automatic selection of fields associated with a viskores::cont::DataSet’s coordinate system.
1    filter.SetPassCoordinateSystems(false);

2.6.2.3. Output Field Names

Many filters will create fields of data. A common way to set the name of the output field is to use the viskores::filter::Filter::SetOutputFieldName() method.

inline void viskores::filter::Filter::SetOutputFieldName(const std::string &name)

Specifies the name of the output field generated.

Not all filters create an output field.

inline const std::string &viskores::filter::Filter::GetOutputFieldName() const

Specifies the name of the output field generated.

Not all filters create an output field.

Most filters will have a default name to use for its generated fields. It is also common for filters to provide convenience methods to name the output fields.