pyvista.CompositeFilters.generic_filter

pyvista.CompositeFilters.generic_filter#

CompositeFilters.generic_filter(
function: str | Callable[..., _TypeMultiBlockLeaf],
/,
*args,
**kwargs,
) MultiBlock[source]#

Apply any filter to all nested blocks recursively.

This filter applies a user-specified function or method to all blocks in this MultiBlock.

Note

If an inplace keyword is used, this MultiBlock is modified in-place along with all blocks.

Note

By default, the specified function is not applied to any None blocks. These are simply skipped and passed through to the output.

For advanced use, it is possible to apply the filter to None blocks by using the undocumented keyword _skip_none=False.

Added in version 0.45.

Parameters:
functionCallable | str

Callable function or name of the method to apply to each block. The function should accept a DataSet as input and return either a DataSet or MultiBlock as output.

*argsAny, optional

Arguments to use with the specified function.

**kwargsAny, optional

Keyword arguments to use with the specified function.

Returns:
MultiBlock

Filtered dataset.

Raises:
RuntimeError

Raised if the filter cannot be applied to any block for any reason. This overrides TypeError, ValueError, AttributeError errors when filtering.

Examples

Create a MultiBlock with various mesh types.

>>> import pyvista as pv
>>> from pyvista import examples
>>> import numpy as np
>>> volume = examples.load_uniform()
>>> poly = examples.load_ant()
>>> unstructured = examples.load_tetbeam()
>>> multi = pv.MultiBlock([volume, poly, unstructured])
>>> type(multi[0]), type(multi[1]), type(multi[2])
(<class 'pyvista.core.grid.ImageData'>, <class 'pyvista.core.pointset.PolyData'>, <class 'pyvista.core.pointset.UnstructuredGrid'>)

Use the generic filter to apply cast_to_unstructured_grid() to all blocks.

>>> filtered = multi.generic_filter('cast_to_unstructured_grid')
>>> type(filtered[0]), type(filtered[1]), type(filtered[2])
(<class 'pyvista.core.pointset.UnstructuredGrid'>, <class 'pyvista.core.pointset.UnstructuredGrid'>, <class 'pyvista.core.pointset.UnstructuredGrid'>)

Use the partition() filter on all blocks. Any arguments can be specified as though the filter is being used directly.

>>> filtered = multi.generic_filter('partition', 4, as_composite=True)

Any function can be used as long as it returns a DataSet or MultiBlock. For example, we can normalize each block independently to have bounds between -0.5 and 0.5.

>>> def normalize_bounds(dataset):
...     # Center the dataset
...     dataset = dataset.translate(-np.array(dataset.center))
...     # Scale the dataset
...     bounds = dataset.bounds
...     x_scale = 1 / (bounds.x_max - bounds.x_min)
...     y_scale = 1 / (bounds.y_max - bounds.y_min)
...     z_scale = 1 / (bounds.z_max - bounds.z_min)
...     return dataset.scale((x_scale, y_scale, z_scale))
>>> filtered = multi.generic_filter(normalize_bounds)
>>> filtered
MultiBlock (...)
  N Blocks:   3
  X Bounds:   -5.000e-01, 5.000e-01
  Y Bounds:   -5.000e-01, 5.000e-01
  Z Bounds:   -5.000e-01, 5.000e-01

The generic filter will fail if the filter can only be applied to some blocks but not others. For example, it is not possible to use the resample() filter generically since the MultiBlock above is heterogeneous and contains some blocks which are not ImageData.

>>> multi.generic_filter('resample', 0.5)
RuntimeError: The filter 'resample' could not be applied to the block at index 1 with name 'Block-01' and type PolyData.

Use a custom function instead to apply the generic filter conditionally. Here we filter the image blocks but simply pass-through a copy of any other blocks.

>>> def conditional_resample(dataset, *args, **kwargs):
...     if isinstance(dataset, pv.ImageData):
...         return dataset.resample(*args, **kwargs)
...     return dataset.copy()
>>> filtered = multi.generic_filter(conditional_resample, 0.5)