Source code for mantidimaging.core.operations.rebin.rebin

# Copyright (C) 2022 ISIS Rutherford Appleton Laboratory UKRI
# SPDX - License - Identifier: GPL-3.0-or-later

from functools import partial
import skimage.transform

from mantidimaging import helper as h
from mantidimaging.core.data import Images
from mantidimaging.core.operations.base_filter import BaseFilter
from mantidimaging.core.parallel import shared as ps
from mantidimaging.core.parallel import utility as pu
from mantidimaging.gui.utility import add_property_to_form
from mantidimaging.gui.utility.qt_helpers import Type


[docs] class RebinFilter(BaseFilter): """Rebin the image to reduce the resolution. This filter temporarily increases memory usage, while the image is being rebinned. The memory usage will be lowered after the filter has finished executing. Intended to be used on: Any data When: If you want to reduce the data size and to smoothen the image. """ filter_name = "Rebin" link_histograms = True
[docs] @staticmethod def filter_func(images: Images, rebin_param=0.5, mode=None, cores=None, chunksize=None, progress=None) -> Images: """ :param images: Sample data which is to be processed. Expects radiograms :param rebin_param: int, float or tuple int - Percentage of current size. float - Fraction of current size. tuple - Size of the output image (x, y). :param mode: Interpolation to use for re-sizing ('nearest', 'lanczos', 'bilinear', 'bicubic' or 'cubic'). :param cores: The number of cores that will be used to process the data. :param chunksize: The number of chunks that each worker will receive. :return: The processed 3D numpy.ndarray """ h.check_data_stack(images) if isinstance(rebin_param, tuple): param_valid = rebin_param[0] > 0 and rebin_param[1] > 0 else: param_valid = rebin_param > 0 if not param_valid: raise ValueError('Rebin parameter must be greater than 0') sample = images.data empty_resized_data = _create_reshaped_array(images, rebin_param) f = ps.create_partial(skimage.transform.resize, ps.return_to_second_at_i, mode=mode, output_shape=empty_resized_data.shape[1:]) ps.shared_list = [sample, empty_resized_data] ps.execute(partial_func=f, num_operations=sample.shape[0], cores=cores, msg="Applying Rebin", progress=progress) images.data = empty_resized_data return images
[docs] @staticmethod def register_gui(form, on_change, view): # Rebin by uniform factor options _, factor = add_property_to_form('Factor', 'float', 0.5, (0.01, 4.0), on_change=on_change, tooltip="Factor by which the data will be rebinned, " "e.g. 0.5 is 50% reduced size", single_step_size=0.05) # Rebin to target shape options shape_range = (1, 9999) _, shape_x = add_property_to_form('X', Type.INT, 100, shape_range, on_change=on_change) _, shape_y = add_property_to_form('Y', Type.INT, 100, shape_range, on_change=on_change) from PyQt5.QtWidgets import QHBoxLayout, QRadioButton, QLabel, QComboBox shape_fields = QHBoxLayout() shape_fields.addWidget(shape_x) shape_fields.addWidget(shape_y) # Rebin dimension selection options rebin_by_factor_radio = QRadioButton("Rebin by Factor") def size_by_factor_toggled(enabled): factor.setEnabled(enabled) on_change() rebin_by_factor_radio.toggled.connect(size_by_factor_toggled) rebin_to_dimensions_radio = QRadioButton("Rebin to Dimensions") def size_by_dimensions_toggled(enabled): shape_x.setEnabled(enabled) shape_y.setEnabled(enabled) on_change() rebin_to_dimensions_radio.toggled.connect(size_by_dimensions_toggled) # Rebin mode options label_mode = QLabel("Mode") mode_field = QComboBox() mode_field.addItems(modes()) form.addRow(rebin_to_dimensions_radio, shape_fields) form.addRow(rebin_by_factor_radio, factor) form.addRow(label_mode, mode_field) # Ensure good default UI state rebin_to_dimensions_radio.setChecked(True) rebin_by_factor_radio.setChecked(True) return { "rebin_to_dimensions_radio": rebin_to_dimensions_radio, "shape_x": shape_x, "shape_y": shape_y, "rebin_by_factor_radio": rebin_by_factor_radio, "factor": factor, "mode_field": mode_field, }
[docs] @staticmethod def execute_wrapper(rebin_to_dimensions_radio=None, shape_x=None, shape_y=None, rebin_by_factor_radio=None, factor=None, mode_field=None): if rebin_to_dimensions_radio.isChecked(): params = (shape_x.value(), shape_y.value()) elif rebin_by_factor_radio.isChecked(): params = factor.value() else: raise ValueError('Unknown bin dimension mode') return partial(RebinFilter.filter_func, mode=mode_field.currentText(), rebin_param=params)
[docs] def modes(): return ["constant", "edge", "wrap", "reflect", "symmetric"]
def _create_reshaped_array(images, rebin_param): old_shape = images.data.shape num_images = old_shape[0] # use SciPy's calculation to find the expected dimensions # int to avoid visible deprecation warning if isinstance(rebin_param, tuple): expected_dimy = int(rebin_param[0]) expected_dimx = int(rebin_param[1]) else: expected_dimy = int(rebin_param * old_shape[1]) expected_dimx = int(rebin_param * old_shape[2]) # allocate memory for images with new dimensions shape = (num_images, expected_dimy, expected_dimx) return pu.create_array(shape, images.dtype)