CompositeFilters.generic_filter

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:
Exception

The error a block raises is re-raised as is, with the index, name and type of that block added to its message.

Changed in version 0.50: The error keeps its own class. Previously every error was replaced by a RuntimeError.

Examples#

Download Python source code | Download Jupyter notebook

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(block) for block in multi]
[<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(block) for block in filtered]
[<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
...     factor = 1 / np.array(dataset.bounds_size)
...     return dataset.scale(factor)
>>> filtered = multi.generic_filter(normalize_bounds)
>>> filtered
MultiBlock[ImageData | PolyData | UnstructuredGrid] (...)
  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)
AttributeError: The filter 'resample'
could not be applied to the block at index 1 with name 'Block-01' and type PolyData:
'PolyData' object has no attribute 'resample'

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)

See Also#

pyvista.MultiBlock.flatten
pyvista.MultiBlock.recursive_iterator
pyvista.MultiBlock.clean