Source code for ewoksxrpd.tasks.mask

from numbers import Number

import numpy
from ewoksdata.data import bliss
from numpy.typing import ArrayLike

from .convolution import gaussian_filter
from .data_access import TaskWithDataAccess
from .morphology import binary_dilation

__all__ = ["MaskDetection"]


[docs] def smooth_mask(mask: ArrayLike, hwhm: Number = 5) -> ArrayLike: """ Extracted from `pyFAI.gui.cli_calibration` """ big_mask = binary_dilation(mask, hwhm) sigma = hwhm / numpy.sqrt(2 * numpy.log(2)) smooth_mask = gaussian_filter(big_mask.astype(numpy.float32), sigma) return smooth_mask.astype(bool)
[docs] class MaskDetection( TaskWithDataAccess, input_names=["image1", "monitor1", "image2", "monitor2"], optional_input_names=["smooth", "monitor_ratio_margin"], output_names=["mask"], ): """The pixels with the same ratio as the monitor ratio within an error margin are considered "good pixels". The others are masked off. The error margin `monitor_ratio_margin` is a fraction of the monitor ratio (0.1 by default). Masked pixels have value `1`. The mask can be smoothed with `smooth > 0` to avoid border effects. .. code: monitor_ratio = monitor_high / monitor_low image_ratio = image_high / image_low bad = abs(image_ratio - monitor_ratio) > monitor_ratio * monitor_ratio_margin """
[docs] def run(self): monitor_high = self.get_data(self.inputs.monitor1) monitor_low = self.get_data(self.inputs.monitor2) image_high = bliss.get_image(self.inputs.image1) image_low = bliss.get_image(self.inputs.image2) if monitor_high < monitor_low: monitor_high, monitor_low = monitor_low, monitor_high image_high, image_low = image_low, image_high monitor_ratio = monitor_high / monitor_low with numpy.errstate(divide="ignore", invalid="ignore"): image_ratio = image_high / image_low monitor_ratio_margin = self.get_input_value("monitor_ratio_margin", default=0.1) threshold = monitor_ratio * monitor_ratio_margin mask = numpy.abs(image_ratio - monitor_ratio) > threshold mask |= ~numpy.isfinite(image_ratio) if self.inputs.smooth: mask = smooth_mask(mask, self.inputs.smooth) self.outputs.mask = mask.astype(numpy.int8)