Filter Base Module#
Module: pyradise.process.base
General#
The filter base module provides the filter base classes (i.e. Filter and
LoopEntryFilter) and their associated filter parameter classes (i.e.
FilterParams and LoopEntryFilterParams). Furthermore,
this module contains the implementation of the filter pipeline class (i.e.
FilterPipeline), which is used to chain multiple parameterized filters such that they
can be executed sequentially on the same subject.
Class Overview#
The following abstract base classes are provided by the base module:
Class |
Description |
|---|---|
Base class for |
|
Base class for |
|
Base class for |
|
Base class for |
|
A class for combining multiple |
Details#
- class FilterParams[source]#
Bases:
ABCAn abstract filter parameter class which provides the parameters used for the configuration of a certain filter. The derived subclasses can hold any set of parameters and is provided to the corresponding
Filtervia theexecute()method. TheFilterParamssubclasses may incorporate also methods to calculate certain parameter values based on the given set of parameters.The instances of
FilterParamssubclasses are stored inside aTransformInfoinstance to keep track of the parameters used during the execution of a certainFiltersuch that invertibility can be guaranteed forFilters feasible to be inverted. However, for the reason of reproducibility theFilterParamsinstances should be tracked always.Example
An example of a
FilterParamsimplementation for an intensity rescaling filter:>>> from pyradise.process import FilterParams >>> >>> >>> class ExampleRescaleFilterParams(FilterParams): >>> >>> def __init__(self, min_out: float, max_out: float) -> None: >>> super().__init__() >>> >>> # reverse the values if min_out > max_out >>> if min_out > max_out: >>> min_out, max_out = max_out, min_out >>> >>> # the minimum and maximum output intensity values >>> self.min_out = min_out >>> self.max_out = max_out
- class Filter(warning_on_non_invertible=False)[source]#
Bases:
ABCAn abstract filter base class which is used to process a subject and its content. In PyRaDiSe a
Filteris the main data processing object which is feasible to modify the structure and content of aSubject, the content of the subject-associatedImageand other subject-associated data. Thus, filters can be used for pre-processing, DL-model inference, and post-processing.The implemented filter design provides a standardized interface such that filters can be chained together in a
FilterPipelineto form a processing pipeline. Furthermore, the extensible implementation renders the tracking of content changes feasible for the purpose of reproducibility and invertibility on invertibleFilter.The
processpackage provides a set of implementedFilters and associatedFilterParams. However, the user may implement its ownFilters depending on the task specific needs. We recommend to share the user-implementedFilters with the community via GitHub or by generating pull requests to the PyRaDiSe GitHub repository. We thank all contributors in advance for sharing their filter implementations!In order to implement a new
Filterthe following steps are required:Always derive from the
Filterclass.Implement the
execute()method and possible subsequent methods which are used to process theSubject.Make sure that your implementation tracks the changes and assign it to the
TransformTapeinstance of the correspondingImageinstance.Implement the
execute_inverse()andis_invertible()methods if the filter is invertible. Please note that the implementation can access all information which was previously recorded on the correspondingTransformTapeinstance.Test the new
Filterimplementation and make sure that it works as expected.
Example
Example implementation of an intensity rescaling filter:
>>> import SimpleITK as sitk >>> import numpy as np >>> >>> from pyradise.process import Filter, FilterParams >>> from pyradise.data import Subject, IntensityImage, TransformInfo >>> >>> >>> class ExampleRescaleFilterParams(FilterParams): >>> >>> def __init__(self, min_out: float, max_out: float) -> None: >>> super().__init__() >>> >>> # reverse the values if min_out > max_out >>> if min_out > max_out: >>> min_out, max_out = max_out, min_out >>> >>> # the minimum and maximum output intensity values >>> self.min_out = min_out >>> self.max_out = max_out >>> >>> >>> class ExampleRescaleFilter(Filter): >>> >>> @staticmethod >>> def is_invertible() -> bool: >>> # return True because the filter is invertible >>> return True >>> >>> def execute(self, >>> subject: Subject, >>> params: ExampleRescaleFilterParams >>> ) -> Subject: >>> # loop through the images >>> for image in subject.get_images(): >>> >>> # exclude segmentation images >>> if not isinstance(image, IntensityImage): >>> continue >>> >>> # retrieve the image data >>> original_image_sitk = image.get_image_data() >>> >>> # rescale the intensity >>> new_image_sitk = sitk.RescaleIntensity(original_image_sitk, >>> params.min_out, >>> params.max_out) >>> >>> # update the image data >>> image.set_image_data(new_image_sitk) >>> >>> # track the necessary information >>> original_image_np = sitk.GetArrayFromImage(original_image_sitk) >>> self.tracking_data['min_'] = float(np.min(original_image_np)) >>> self.tracking_data['max_'] = float(np.max(original_image_np)) >>> self._register_tracked_data(image, original_image_sitk, >>> new_image_sitk, params) >>> >>> return subject >>> >>> def execute_inverse(self, >>> subject: Subject, >>> transform_info: TransformInfo, >>> target_image: Optional[Union[SegmentationImage, IntensityImage]] = None >>> ) -> Subject: >>> # loop through the images >>> for image in subject.get_images(): >>> >>> # exclude segmentation images >>> if not isinstance(image, IntensityImage): >>> continue >>> >>> # retrieve the tracked data >>> min_intensity = transform_info.get_data('min_') >>> max_intensity = transform_info.get_data('max_') >>> >>> # undo the intensity rescaling >>> original_image_sitk = image.get_image_data() >>> new_image_sitk = sitk.RescaleIntensity(original_image_sitk, >>> min_intensity, >>> max_intensity) >>> >>> # update the image data >>> image.set_image_data(new_image_sitk) >>> >>> # there is no need to track information because >>> # the operation is inverted >>> >>> return subject
- Parameters:
warning_on_non_invertible (bool) – If True, a warning is printed to the console if a filter is called to execute the invertible process but is not invertible (default: False).
- abstract static is_invertible()[source]#
Check if the filter is invertible.
- Returns:
True if the filter is invertible, otherwise False.
- Return type:
bool
- set_verbose(verbose)[source]#
Set the verbose state.
- Parameters:
verbose (bool) – If True, the filter outputs information to the console, otherwise not.
- Return type:
None- Returns:
None
- set_warning_on_non_invertible(warn)[source]#
Set the warning state.
- Parameters:
warn (bool) – If True, the filter outputs a warning if the filter is called and is not invertible, otherwise not.
- Return type:
None- Returns:
None
- abstract execute(subject, params)[source]#
Execute the filter on the provided
Subjectinstance.Note
For the ease of use, the filter provides a private
_create_transform_info()method which can be used to create theTransformInfoinstances.Important
The filter is responsible to record the transformations applied to each image such that the invertibility is ensured. Even if the filter is not invertible, the transformations should be recorded such that the order of filter applications can be reconstructed from the transform tapes of the images. In case the filter is not invertible, the
is_invertible()must returnFalse.- Parameters:
subject (Subject) – The subject to be processed.
params (Optional[FilterParams]) – The filter parameters, if required.
- Returns:
The processed subject.
- Return type:
- abstract execute_inverse(subject, transform_info, target_image=None)[source]#
Execute the filter inversely if possible. Typically, this method gets a temporary subject which contains a single image because the recording of the transformations is image dependent and inappropriate inverse transformations would be applied to the other images. However, this method can also be applied to a whole subject to apply the inverse transformations to all images. This approach provides a more flexible way to handle invertibility of transformations.
Important
If the filter is not invertible, the subject must be returned unchanged and the
is_invertible()must returnFalse.- Parameters:
subject (Subject) – The subject to be processed.
transform_info (TransformInfo) – The
TransformInfoinstance.target_image (Optional[Union[SegmentationImage, IntensityImage]]) – The target image to which the inverse transformation should be applied. If None, the inverse transformation is applied to all images (default: None).
- Returns:
The processed subject.
- Return type:
- class LoopEntryFilterParams(loop_axis=None)[source]#
Bases:
FilterParamsAn abstract filter parameter class which provides in addition to
FilterParamstheloop_axisparameter which is used to specify the axis to loop over in theLoopEntryFilter.- Parameters:
loop_axis (Optional[int]) – The axis along which the data transformation is performed. If
None, the transformation is performed on the whole image at once. If a value is given, the transformation is performed by looping over the corresponding image dimension.
- class LoopEntryFilter(warning_on_non_invertible=False)[source]#
Bases:
FilterAn abstract filter base class which is feasible to process images slice-wise in a loop over a defined
loop_axis. Theloop_axismust be specified in the appropriateFilterParamsinstance and if it takes a value ofNone, the filter is executed on the whole image extent at once.- Reference:
The implementation of this class is inspired by an earlier version of the pymia package.
- abstract static is_invertible()[source]#
Check if the filter is invertible.
- Returns:
True if the filter is invertible, otherwise False.
- Return type:
bool
- static loop_entries(data, params, filter_fn, loop_axis)[source]#
Apply the function
filter_fn()by looping over the image using the provided parameters (i.e.params).- Parameters:
data (np.ndarray) – The data to be processed.
params (Any) – The parameters for the filter function.
filter_fn (Callable[[np.ndarray, Any], np.ndarray]) – The filter function.
loop_axis (Optional[int]) – The axis to loop over. If
Nonethe whole image is taken, otherwise the respective dimension.
- Returns:
The processed data.
- Return type:
np.ndarray
- abstract execute(subject, params)[source]#
Execute the filter on the provided
Subjectinstance.Note
For the ease of use, the filter provides a private
_create_transform_info()method which can be used to create theTransformInfoinstances.Important
The filter is responsible to record the transformations applied to each image such that the invertibility is ensured. Even if the filter is not invertible, the transformations should be recorded such that the order of filter applications can be reconstructed from the transform tapes of the images. In case the filter is not invertible, the
is_invertible()must returnFalse.- Parameters:
subject (Subject) – The subject to be processed.
params (Optional[LoopEntryFilterParams]) – The filter parameters, if required.
- Returns:
The processed subject.
- Return type:
- abstract execute_inverse(subject, transform_info, target_image=None)[source]#
Execute the filter inversely if possible. Typically, this method gets a temporary subject which contains a single image because the recording of the transformations is image dependent and inappropriate inverse transformations would be applied to the other images. However, this method can also be applied to a whole subject to apply the inverse transformations to all images. This approach provides a more flexible way to handle invertibility of transformations.
Important
If the filter is not invertible, the subject must be returned unchanged and the
is_invertible()must returnFalse.- Parameters:
subject (Subject) – The subject to be processed.
transform_info (TransformInfo) – The
TransformInfoinstance.target_image (Optional[Union[SegmentationImage, IntensityImage]]) – The target image to which the inverse transformation should be applied. If None, the inverse transformation is applied to all images (default: None).
- Returns:
The processed subject.
- Return type:
- set_verbose(verbose)#
Set the verbose state.
- Parameters:
verbose (bool) – If True, the filter outputs information to the console, otherwise not.
- Return type:
None- Returns:
None
- set_warning_on_non_invertible(warn)#
Set the warning state.
- Parameters:
warn (bool) – If True, the filter outputs a warning if the filter is called and is not invertible, otherwise not.
- Return type:
None- Returns:
None
- class FilterPipeline(filters=None, params=None, warning_on_non_invertible=False)[source]#
Bases:
objectA filter pipeline class which can combine multiple
Filterinstances into one pipeline of sequential filter. This reduces the amount of boilerplate code for the user and provides a nice way to chain multiple filters together.- Parameters:
filters (Optional[Tuple[Filter, ...]]) – The filters of the pipeline (default: None).
params (Optional[Tuple[FilterParams, ...]]) – The parameters for the filters in the pipeline.
warning_on_non_invertible (bool) – If True, a warning is printed to the console if a filter is called to execute the invertible process but is not invertible (default: False).
- set_verbose_all(verbose)[source]#
Set the verbose state for all
Filterinstances.- Parameters:
verbose (bool) – If True the filters print information to the console, otherwise not.
- Return type:
None- Returns:
None
- add_filter(filter_, params=None)[source]#
Add a
Filterinstance and its correspondingFilterParamsto the pipeline.- Parameters:
params (Optional[FilterParams]) – The
FilterParamsinstance to add, if necessary (default: None).
- Return type:
None- Returns:
None
- set_param(params, filter_index)[source]#
Set the
FilterParamsfor a specificFilterinstance at indexfilter_index.- Parameters:
params (FilterParams) – The
FilterParamsinstance.filter_index (int) – The index of the
Filterto add the parameters to.
- Return type:
None- Returns:
None
- add_logger(logger)[source]#
Add a logger to the filter pipeline.
- Parameters:
logger (logging.Logger) – The logger to use with the pipeline.
- Return type:
None- Returns:
None