Ejemplo n.º 1
0
 def test_chunk_bytes_indirectly(self):
     s = EBSD(np.zeros((10, 10, 8, 8)))
     array_out0 = get_dask_array(s)
     array_out1 = get_dask_array(s, chunk_bytes="25KiB")
     array_out2 = get_dask_array(s, chunk_bytes=25e3)
     assert array_out0.chunksize != array_out1.chunksize
     assert array_out1.chunksize == array_out2.chunksize
Ejemplo n.º 2
0
    def test_get_dask_array(self):
        s = EBSD((255 * np.random.rand(10, 10, 120, 120)).astype(np.uint8))
        dask_array = get_dask_array(s, chunk_shape=8)
        assert dask_array.chunksize == (8, 8, 120, 120)

        # Make data lazy
        s.data = dask_array.rechunk((5, 5, 120, 120))
        dask_array = get_dask_array(s)
        assert dask_array.chunksize == (5, 5, 120, 120)
Ejemplo n.º 3
0
    def test_get_dynamic_background_frequency(self, dummy_signal, std, answer):

        dtype_out = answer.dtype

        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        kwargs = {}
        (
            kwargs["fft_shape"],
            kwargs["window_shape"],
            kwargs["transfer_function"],
            kwargs["offset_before_fft"],
            kwargs["offset_after_ifft"],
        ) = _dynamic_background_frequency_space_setup(
            pattern_shape=dummy_signal.axes_manager.signal_shape[::-1],
            std=std,
            truncate=4.0,
        )

        background = dask_array.map_blocks(
            func=chunk.get_dynamic_background,
            filter_func=_fft_filter,
            dtype_out=dtype_out,
            dtype=dtype_out,
            **kwargs,
        )

        # Check for correct data type and gives expected output intensities
        assert background.dtype == dtype_out
        assert np.allclose(background[0, 0].compute(), answer, atol=1e-4)
Ejemplo n.º 4
0
    def test_rescale_intensity(self, dummy_signal, dtype_out, answer):
        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        rescaled_patterns = dask_array.map_blocks(func=chunk.rescale_intensity,
                                                  dtype_out=dtype_out,
                                                  dtype=dtype_out)

        assert isinstance(rescaled_patterns, da.Array)
        assert rescaled_patterns.dtype == dtype_out
        assert np.allclose(rescaled_patterns[0, 0].compute(),
                           answer,
                           atol=1e-4)
Ejemplo n.º 5
0
    def test_adaptive_histogram_equalization_chunk(self, dummy_signal):
        dask_array = get_dask_array(dummy_signal)
        dtype_out = dask_array.dtype
        kernel_size = (10, 10)
        nbins = 128
        equalized_patterns = dask_array.map_blocks(
            func=chunk.adaptive_histogram_equalization,
            kernel_size=kernel_size,
            nbins=nbins,
        )

        # Check for correct data type and gives expected output intensities
        assert equalized_patterns.dtype == dtype_out
        assert np.allclose(equalized_patterns[0, 0].compute(), ADAPT_EQ_UINT8)
Ejemplo n.º 6
0
    def test_rescale_intensity_in_range(self, dummy_signal, in_range, answer):
        dtype_out = dummy_signal.data.dtype
        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        rescaled_patterns = dask_array.map_blocks(
            func=chunk.rescale_intensity,
            in_range=in_range,
            dtype_out=dtype_out,
            dtype=dtype_out,
        )

        assert isinstance(rescaled_patterns, da.Array)
        assert rescaled_patterns.dtype == dtype_out
        assert np.allclose(rescaled_patterns[0, 0].compute(), answer)
Ejemplo n.º 7
0
    def test_get_dynamic_background_spatial(self, dummy_signal, std, answer):
        filter_func = gaussian_filter
        kwargs = {"sigma": std}

        dtype_out = np.uint8
        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        background = dask_array.map_blocks(
            func=chunk.get_dynamic_background,
            filter_func=filter_func,
            dtype_out=dtype_out,
            dtype=dtype_out,
            **kwargs,
        )
        assert background.dtype == dtype_out
        assert np.allclose(background[0, 0].compute(), answer)
Ejemplo n.º 8
0
    def test_remove_dynamic_background_spatial_uint16(self, dummy_signal):
        dtype_out = np.uint16

        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        corrected_patterns = dask_array.map_blocks(
            func=chunk.remove_dynamic_background,
            filter_func=gaussian_filter,
            operation_func=np.subtract,
            dtype_out=dtype_out,
            dtype=dtype_out,
            sigma=2,
        )

        # Check for correct data type and gives expected output intensities
        assert corrected_patterns.dtype == dtype_out
        assert np.allclose(corrected_patterns[0, 0].compute(),
                           DYN_CORR_UINT16_SPATIAL_STD2)
Ejemplo n.º 9
0
    def test_remove_static_background_chunk_scalebg(self, dummy_signal,
                                                    dummy_background):
        dtype_out = dummy_signal.data.dtype.type
        dtype_proc = np.float32

        dask_array = get_dask_array(dummy_signal, dtype=dtype_proc)

        corrected_patterns = dask_array.map_blocks(
            func=chunk.remove_static_background,
            static_bg=dummy_background.astype(dtype_proc),
            operation_func=np.subtract,
            dtype_out=dtype_out,
            scale_bg=True,
            dtype=dtype_out,
        )

        assert corrected_patterns.dtype == dtype_out
        assert np.allclose(corrected_patterns[0, 0].compute(),
                           STATIC_SUB_SCALEBG_UINT8)
Ejemplo n.º 10
0
    def test_remove_static_background_chunk(self, dummy_signal,
                                            dummy_background, operation_func,
                                            answer):
        dtype_out = dummy_signal.data.dtype.type
        dtype_proc = np.float32

        dask_array = get_dask_array(dummy_signal, dtype=dtype_proc)
        corrected_patterns = dask_array.map_blocks(
            func=chunk.remove_static_background,
            static_bg=dummy_background.astype(dtype_proc),
            operation_func=operation_func,
            dtype_out=dtype_out,
            dtype=dtype_out,
        )

        # Check for correct data type and gives expected output intensities
        assert corrected_patterns.dtype == dtype_out
        assert isinstance(corrected_patterns, da.Array)
        assert np.allclose(corrected_patterns[0, 0].compute(), answer)
Ejemplo n.º 11
0
    def test_rescale_intensity_percentiles(self, dummy_signal, percentiles,
                                           answer):
        dtype_out = dummy_signal.data.dtype
        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        rescaled_patterns = dask_array.map_blocks(
            func=chunk.rescale_intensity,
            percentiles=percentiles,
            dtype_out=dtype_out,
            dtype=dtype_out,
        )

        p1 = rescaled_patterns[0, 0].compute()
        p2 = rescaled_patterns[0, 1].compute()

        assert isinstance(rescaled_patterns, da.Array)
        assert rescaled_patterns.dtype == dtype_out
        assert np.allclose(p1, answer)
        assert not np.allclose(p1, p2, atol=1)
Ejemplo n.º 12
0
    def test_remove_dynamic_background_spatial(self, dummy_signal, std,
                                               answer):
        dtype_out = dummy_signal.data.dtype.type

        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        kwargs = {"sigma": std}

        corrected_patterns = dask_array.map_blocks(
            func=chunk.remove_dynamic_background,
            filter_func=gaussian_filter,
            operation_func=np.subtract,
            dtype_out=dtype_out,
            dtype=dtype_out,
            **kwargs,
        )

        # Check for correct data type and gives expected output intensities
        assert corrected_patterns.dtype == dtype_out
        assert np.allclose(corrected_patterns[0, 0].compute(), answer)
Ejemplo n.º 13
0
    def test_average_neighbour_patterns_chunk(self, dummy_signal, dtype_in):
        w = Window()

        # Get array to operate on
        dask_array = get_dask_array(dummy_signal)
        dtype_out = dask_array.dtype

        # Get sum of window data for each image
        nav_shape = dummy_signal.axes_manager.navigation_shape
        w_sums = convolve(
            input=np.ones(nav_shape[::-1], dtype=int),
            weights=w.data,
            mode="constant",
            cval=0,
        )

        # Add signal dimensions to arrays to enable their use with
        # Dask's map_blocks()
        sig_dim = dummy_signal.axes_manager.signal_dimension
        nav_dim = dummy_signal.axes_manager.navigation_dimension
        for _ in range(sig_dim):
            w_sums = np.expand_dims(w_sums, axis=w_sums.ndim)
            w = np.expand_dims(w, axis=w.ndim)
        w_sums = da.from_array(w_sums,
                               chunks=dask_array.chunks[:nav_dim] +
                               (1, ) * sig_dim)

        averaged_patterns = dask_array.map_blocks(
            func=chunk.average_neighbour_patterns,
            window_sums=w_sums,
            window=w,
            dtype_out=dtype_in,
            dtype=dtype_out,
        )

        answer = np.array([255, 109, 218, 218, 36, 236, 255, 36, 0],
                          dtype=np.uint8).reshape((3, 3))

        # Check for correct data type and gives expected output intensities
        assert averaged_patterns.dtype == dtype_out
        assert np.allclose(averaged_patterns[0, 0].compute(), answer)
Ejemplo n.º 14
0
    def test_remove_dynamic_background_out_range(self, dummy_signal, omax,
                                                 answer):
        dtype_out = dummy_signal.data.dtype.type

        out_range = (0, omax)

        dask_array = get_dask_array(dummy_signal, dtype=np.float32)

        corrected_patterns = dask_array.map_blocks(
            func=chunk.remove_dynamic_background,
            filter_func=gaussian_filter,
            operation_func=np.subtract,
            sigma=2,
            out_range=out_range,
            dtype_out=dtype_out,
            dtype=dtype_out,
        )

        assert corrected_patterns.dtype == dtype_out
        assert corrected_patterns.max().compute() == omax
        assert np.allclose(corrected_patterns[0, 0].compute(), answer)
Ejemplo n.º 15
0
    def rescale_intensity(
        self,
        relative: bool = False,
        in_range: Union[None, Tuple[int, int], Tuple[float, float]] = None,
        out_range: Union[None, Tuple[int, int], Tuple[float, float]] = None,
        dtype_out: Union[
            None, np.dtype, Tuple[int, int], Tuple[float, float]
        ] = None,
        percentiles: Union[None, Tuple[int, int], Tuple[float, float]] = None,
    ):
        """Rescale image intensities inplace.

        Output min./max. intensity is determined from `out_range` or the
        data type range of the :class:`numpy.dtype` passed to
        `dtype_out` if `out_range` is None.

        This method is based on
        :func:`skimage.exposure.rescale_intensity`.

        Parameters
        ----------
        relative
            Whether to keep relative intensities between images (default
            is False). If True, `in_range` must be None, because
            `in_range` is in this case set to the global min./max.
            intensity.
        in_range
            Min./max. intensity of input images. If None (default),
            `in_range` is set to pattern min./max intensity. Contrast
            stretching is performed when `in_range` is set to a narrower
            intensity range than the input patterns. Must be None if
            `relative` is True or `percentiles` are passed.
        out_range
            Min./max. intensity of output images. If None (default),
            `out_range` is set to `dtype_out` min./max according to
            `skimage.util.dtype.dtype_range`.
        dtype_out
            Data type of rescaled images, default is input images' data
            type.
        percentiles
            Disregard intensities outside these percentiles. Calculated
            per image. Must be None if `in_range` or `relative` is
            passed. Default is None.

        See Also
        --------
        kikuchipy.pattern.rescale_intensity,
        :func:`skimage.exposure.rescale_intensity`

        Examples
        --------
        Image intensities are stretched to fill the available grey
        levels in the input images' data type range or any
        :class:`numpy.dtype` range passed to `dtype_out`, either
        keeping relative intensities between images or not:

        >>> print(s.data.dtype_out, s.data.min(), s.data.max(),
        ...       s.inav[0, 0].data.min(), s.inav[0, 0].data.max())
        uint8 20 254 24 233
        >>> s2 = s.deepcopy()
        >>> s.rescale_intensity(dtype_out=np.uint16)
        >>> print(s.data.dtype_out, s.data.min(), s.data.max(),
        ...       s.inav[0, 0].data.min(), s.inav[0, 0].data.max())
        uint16 0 65535 0 65535
        >>> s2.rescale_intensity(relative=True)
        >>> print(s2.data.dtype_out, s2.data.min(), s2.data.max(),
        ...       s2.inav[0, 0].data.min(), s2.inav[0, 0].data.max())
        uint8 0 255 4 232

        Contrast stretching can be performed by passing percentiles:

        >>> s.rescale_intensity(percentiles=(1, 99))

        Here, the darkest and brightest pixels within the 1% percentile
        are set to the ends of the data type range, e.g. 0 and 255
        respectively for images of ``uint8`` data type.

        Notes
        -----
        Rescaling RGB images is not possible. Use RGB channel
        normalization when creating the image instead.
        """
        if self.data.dtype in rgb_dtypes.values():
            raise NotImplementedError(
                "Use RGB channel normalization when creating the image instead."
            )

        # Determine min./max. intensity of input image to rescale to
        if in_range is not None and percentiles is not None:
            raise ValueError(
                "'percentiles' must be None if 'in_range' is not None."
            )
        elif relative is True and in_range is not None:
            raise ValueError("'in_range' must be None if 'relative' is True.")
        elif relative:  # Scale relative to min./max. intensity in images
            in_range = (self.data.min(), self.data.max())

        if dtype_out is None:
            dtype_out = self.data.dtype.type

        if out_range is None:
            dtype_out_pass = dtype_out
            if isinstance(dtype_out, np.dtype):
                dtype_out_pass = dtype_out.type
            out_range = dtype_range[dtype_out_pass]

        # Create dask array of signal images and do processing on this
        dask_array = get_dask_array(signal=self)

        # Rescale images
        rescaled_images = dask_array.map_blocks(
            func=chunk.rescale_intensity,
            in_range=in_range,
            out_range=out_range,
            dtype_out=dtype_out,
            percentiles=percentiles,
            dtype=dtype_out,
        )

        # Overwrite signal images
        if not self._lazy:
            with ProgressBar():
                if self.data.dtype != rescaled_images.dtype:
                    self.change_dtype(dtype_out)
                print("Rescaling the image intensities:", file=sys.stdout)
                rescaled_images.store(self.data, compute=True)
        else:
            self.data = rescaled_images
Ejemplo n.º 16
0
    def normalize_intensity(
        self,
        num_std: int = 1,
        divide_by_square_root: bool = False,
        dtype_out: Optional[np.dtype] = None,
    ):
        """Normalize image intensities in inplace to a mean of zero with
        a given standard deviation.

        Parameters
        ----------
        num_std
            Number of standard deviations of the output intensities.
            Default is 1.
        divide_by_square_root
            Whether to divide output intensities by the square root of
            the signal dimension size. Default is False.
        dtype_out
            Data type of normalized images. If None (default), the input
            images' data type is used.

        Notes
        -----
        Data type should always be changed to floating point, e.g.
        ``np.float32`` with
        :meth:`~hyperspy.signal.BaseSignal.change_dtype`, before
        normalizing the intensities.

        Examples
        --------
        >>> np.mean(s.data)
        146.0670987654321
        >>> s.change_dtype(np.float32)  # Or passing dtype_out=np.float32
        >>> s.normalize_intensity()
        >>> np.mean(s.data)
        2.6373216e-08

        Notes
        -----
        Rescaling RGB images is not possible. Use RGB channel
        normalization when creating the image instead.
        """
        if self.data.dtype in rgb_dtypes.values():
            raise NotImplementedError(
                "Use RGB channel normalization when creating the image instead."
            )

        if dtype_out is None:
            dtype_out = self.data.dtype

        dask_array = get_dask_array(self, dtype=np.float32)

        normalized_images = dask_array.map_blocks(
            func=chunk.normalize_intensity,
            num_std=num_std,
            divide_by_square_root=divide_by_square_root,
            dtype_out=dtype_out,
            dtype=dtype_out,
        )

        # Change data type if requested
        if dtype_out != self.data.dtype:
            self.change_dtype(dtype_out)

        # Overwrite signal patterns
        if not self._lazy:
            with ProgressBar():
                print("Normalizing the image intensities:", file=sys.stdout)
                normalized_images.store(self.data, compute=True)
        else:
            self.data = normalized_images