示例#1
0
def _make_centre_array_from_signal(signal, x=None, y=None):
    a_m = signal.axes_manager
    shape = a_m.navigation_shape[::-1]
    if x is None:
        centre_x_array = np.ones(shape) * a_m.signal_axes[0].value2index(0)
    else:
        centre_x_array = np.ones(shape) * x
    if y is None:
        centre_y_array = np.ones(shape) * a_m.signal_axes[1].value2index(0)
    else:
        centre_y_array = np.ones(shape) * y
    if not isiterable(centre_x_array):
        centre_x_array = np.array([centre_x_array])
    if not isiterable(centre_y_array):
        centre_y_array = np.array([centre_y_array])
    return (centre_x_array, centre_y_array)
示例#2
0
def _filter_peak_array_radius(peak_array, xc, yc, r_min=None, r_max=None):
    """Remove peaks from a peak_array, based on distance from a point.

    Parameters
    ----------
    peak_array : NumPy array
        In the form [[[[y0, x0], [y1, x1]]]]
    xc, yc : scalars, NumPy array
        Centre position
    r_min, r_max : scalar
        Remove peaks which are within r_min and r_max distance from the centre.
        One of them must be specified.

    Returns
    -------
    peak_array_filtered : NumPy array
        Similar to peak_array input, but with the too-close peaks
        removed.

    See Also
    --------
    _filter_peak_list
    _filter_4D_peak_array
    _filter_peak_list_radius

    """
    if not isiterable(xc):
        xc = np.ones(peak_array.shape[:2]) * xc
    if not isiterable(yc):
        yc = np.ones(peak_array.shape[:2]) * yc
    peak_array_filtered = np.empty(shape=peak_array.shape[:2], dtype=object)
    for iy, ix in np.ndindex(peak_array.shape[:2]):
        temp_xc, temp_yc = xc[iy, ix], yc[iy, ix]
        peak_list_filtered = _filter_peak_list_radius(peak_array[iy, ix],
                                                      xc=temp_xc,
                                                      yc=temp_yc,
                                                      r_min=r_min,
                                                      r_max=r_max)
        peak_array_filtered[iy, ix] = np.array(peak_list_filtered)
    return peak_array_filtered
示例#3
0
文件: eels.py 项目: gdonval/hyperspy
    def add_elements(self, elements, include_pre_edges=False):
        """Declare the elemental composition of the sample.

        The ionisation edges of the elements present in the current
        energy range will be added automatically.

        Parameters
        ----------
        elements : tuple of strings
            The symbol of the elements. Note this input must always be
            in the form of a tuple. Meaning: add_elements(('C',)) will
            work, while add_elements(('C')) will NOT work.
        include_pre_edges : bool
            If True, the ionization edges with an onset below the lower
            energy limit of the SI will be incluided

        Examples
        --------

        >>> s = signals.EELSSpectrum(np.arange(1024))
        >>> s.add_elements(('C', 'O'))
        Adding C_K subshell
        Adding O_K subshell

        Raises
        ------
        ValueError

        """
        if not isiterable(elements) or isinstance(elements, basestring):
            raise ValueError(
                "Input must be in the form of a tuple. For example, "
                "if `s` is the variable containing this EELS spectrum:\n "
                ">>> s.add_elements(('C',))\n"
                "See the docstring for more information.")

        for element in elements:
            if element in elements_db:
                self.elements.add(element)
            else:
                raise ValueError(
                    "%s is not a valid symbol of a chemical element"
                    % element)
        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')
        self.metadata.Sample.elements = list(self.elements)
        if self.elements:
            self.generate_subshells(include_pre_edges)
示例#4
0
文件: eels.py 项目: jonpdx/hyperspy
    def add_elements(self, elements, include_pre_edges=False):
        """Declare the elemental composition of the sample.

        The ionisation edges of the elements present in the current
        energy range will be added automatically.

        Parameters
        ----------
        elements : tuple of strings
            The symbol of the elements. Note this input must always be
            in the form of a tuple. Meaning: add_elements(('C',)) will
            work, while add_elements(('C')) will NOT work.
        include_pre_edges : bool
            If True, the ionization edges with an onset below the lower
            energy limit of the SI will be incluided

        Examples
        --------

        >>> s = signals.EELSSpectrum(np.arange(1024))
        >>> s.add_elements(('C', 'O'))
        Adding C_K subshell
        Adding O_K subshell

        Raises
        ------
        ValueError

        """
        if not isiterable(elements) or isinstance(elements, basestring):
            raise ValueError(
                "Input must be in the form of a tuple. For example, "
                "if `s` is the variable containing this EELS spectrum:\n "
                ">>> s.add_elements(('C',))\n"
                "See the docstring for more information.")

        for element in elements:
            if element in elements_db:
                self.elements.add(element)
            else:
                raise ValueError(
                    "%s is not a valid symbol of a chemical element" % element)
        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')
        self.metadata.Sample.elements = list(self.elements)
        if self.elements:
            self.generate_subshells(include_pre_edges)
示例#5
0
文件: eds.py 项目: AakashV/hyperspy
    def add_elements(self, elements):
        """Add elements and the corresponding X-ray lines.

        The list of elements is stored in `metadata.Sample.elements`

        Parameters
        ----------
        elements : list of strings
            The symbol of the elements.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> print(s.metadata.Sample.elements)
        >>> s.add_elements(['Ar'])
        >>> print(s.metadata.Sample.elements)
        ['Al' 'C' 'Cu' 'Mn' 'Zr']
        ['Al', 'Ar', 'C', 'Cu', 'Mn', 'Zr']

        See also
        --------
        set_elements, add_lines, set_lines

        """
        if not isiterable(elements) or isinstance(elements, str):
            raise ValueError(
                "Input must be in the form of a list. For example, "
                "if `s` is the variable containing this EDS spectrum:\n "
                ">>> s.add_elements(('C',))\n"
                "See the docstring for more information.")
        if "Sample.elements" in self.metadata:
            elements_ = set(self.metadata.Sample.elements)
        else:
            elements_ = set()
        for element in elements:
            if element in elements_db:
                elements_.add(element)
            else:
                raise ValueError(
                    "%s is not a valid chemical element symbol." % element)

        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')

        self.metadata.Sample.elements = sorted(list(elements_))
示例#6
0
文件: eds.py 项目: fvoisard2/hyperspy
    def add_elements(self, elements):
        """Add elements and the corresponding X-ray lines.

        The list of elements is stored in `metadata.Sample.elements`

        Parameters
        ----------
        elements : list of strings
            The symbol of the elements.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> print(s.metadata.Sample.elements)
        >>> s.add_elements(['Ar'])
        >>> print(s.metadata.Sample.elements)
        ['Al' 'C' 'Cu' 'Mn' 'Zr']
        ['Al', 'Ar', 'C', 'Cu', 'Mn', 'Zr']

        See also
        --------
        set_elements, add_lines, set_lines

        """
        if not isiterable(elements) or isinstance(elements, str):
            raise ValueError(
                "Input must be in the form of a list. For example, "
                "if `s` is the variable containing this EDS spectrum:\n "
                ">>> s.add_elements(('C',))\n"
                "See the docstring for more information.")
        if "Sample.elements" in self.metadata:
            elements_ = set(self.metadata.Sample.elements)
        else:
            elements_ = set()
        for element in elements:
            if element in elements_db:
                elements_.add(element)
            else:
                raise ValueError("%s is not a valid chemical element symbol." %
                                 element)

        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')

        self.metadata.Sample.elements = sorted(list(elements_))
示例#7
0
    def _set_axis_attribute_values(self, attr, values):
        """Set the given attribute of all the axes to the given
        value(s)

        Parameters
        ----------
        attr : string
            The DataAxis attribute to set.
        values: any
            If iterable, it must have the same number of items
            as axes are in this AxesManager instance. If not iterable,
            the attribute of all the axes are set to the given value.

        """
        if not isiterable(values):
            values = [values] * len(self._axes)
        elif len(values) != len(self._axes):
            raise ValueError("Values must have the same number" "of items are axes are in this AxesManager")
        for axis, value in zip(self._axes, values):
            setattr(axis, attr, value)
示例#8
0
文件: axes.py 项目: lu-chi/hyperspy
    def _set_axis_attribute_values(self, attr, values):
        """Set the given attribute of all the axes to the given
        value(s)

        Parameters
        ----------
        attr : string
            The DataAxis attribute to set.
        values: any
            If iterable, it must have the same number of items
            as axes are in this AxesManager instance. If not iterable,
            the attribute of all the axes are set to the given value.

        """
        if not isiterable(values):
            values = [values, ] * len(self._axes)
        elif len(values) != len(self._axes):
            raise ValueError("Values must have the same number"
                             "of items are axes are in this AxesManager")
        for axis, value in zip(self._axes, values):
            setattr(axis, attr, value)
示例#9
0
 def add_elements(self, elements):
     """Add elements and the corresponding X-ray lines.
     
     The list of elements is stored in `mapped_parameters.Sample.elements`     
     
     Parameters
     ----------
     elements : list of strings
         The symbol of the elements.  
     
         
     See also
     --------
     set_elements, add_lines, set_lines.
     
     """
     if not isiterable(elements) or isinstance(elements, basestring):
         raise ValueError(
         "Input must be in the form of a list. For example, "
         "if `s` is the variable containing this EELS spectrum:\n "
         ">>> s.add_elements(('C',))\n"
         "See the docstring for more information.")
     if "Sample.elements" in self.mapped_parameters:
         elements_ = set(self.mapped_parameters.Sample.elements)
     else:
         elements_ = set()
     for element in elements:            
         if element in elements_db:               
             elements_.add(element)
         else:
             raise ValueError(
                 "%s is not a valid chemical element symbol." % element)
                
     if not hasattr(self.mapped_parameters, 'Sample'):
         self.mapped_parameters.add_node('Sample')
         
     self.mapped_parameters.Sample.elements = sorted(list(elements_))
示例#10
0
文件: eds.py 项目: mfm24/hyperspy
    def add_elements(self, elements):
        """Add elements and the corresponding X-ray lines.
        
        The list of elements is stored in `mapped_parameters.Sample.elements`     
        
        Parameters
        ----------
        elements : list of strings
            The symbol of the elements.  
        
            
        See also
        --------
        set_elements, add_lines, set_lines.
        
        """
        if not isiterable(elements) or isinstance(elements, basestring):
            raise ValueError(
                "Input must be in the form of a list. For example, "
                "if `s` is the variable containing this EELS spectrum:\n "
                ">>> s.add_elements(('C',))\n"
                "See the docstring for more information.")
        if "Sample.elements" in self.mapped_parameters:
            elements_ = set(self.mapped_parameters.Sample.elements)
        else:
            elements_ = set()
        for element in elements:
            if element in elements_db:
                elements_.add(element)
            else:
                raise ValueError("%s is not a valid chemical element symbol." %
                                 element)

        if not hasattr(self.mapped_parameters, 'Sample'):
            self.mapped_parameters.add_node('Sample')

        self.mapped_parameters.Sample.elements = sorted(list(elements_))
示例#11
0
def get_gui(self, toolkey, display=True, toolkit=None, **kwargs):
    if not TOOLKIT_REGISTRY:
        raise ImportError(
            "No toolkit registered. Install hyperspy_gui_ipywidgets or "
            "hyperspy_gui_traitsui GUI elements. If hyperspy_gui_traits"
            "is installed, initialize a toolkit supported by traitsui "
            "before importing HyperSpy."
        )
    from hyperspy.defaults_parser import preferences
    if isinstance(toolkit, str):
        toolkit = (toolkit,)
    if isiterable(toolkit):
        toolkits = set()
        for tk in toolkit:
            if tk in TOOLKIT_REGISTRY:
                toolkits.add(tk)
            else:
                raise ValueError(
                    "{} is not a registered toolkit.".format(tk)
                )
    elif toolkit is None:
        toolkits = set()
        available_disabled_toolkits = set()
        if "ipywidgets" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_ipywidgets_gui:
                toolkits.add("ipywidgets")
            else:
                available_disabled_toolkits.add("ipywidgets")
        if "traitsui" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_traitsui_gui:
                toolkits.add("traitsui")
            else:
                available_disabled_toolkits.add("traitsui")
        if not toolkits and available_disabled_toolkits:
            is_or_are = "is" if len(
                available_disabled_toolkits) == 1 else "are"
            them_or_it = ("it" if len(available_disabled_toolkits) == 1
                          else "them")
            raise ValueError(
                "No toolkit available. The {} {} installed but "
                "disabled in `preferences`. Enable {} in `preferences` or "
                "manually select a toolkit with the `toolkit` argument.".format(
                    _toolkits_to_string(available_disabled_toolkits),
                    is_or_are, them_or_it)
            )

    else:
        raise ValueError(
            "`toolkit` must be a string, an iterable of strings or None.")
    if toolkey not in UI_REGISTRY or not UI_REGISTRY[toolkey]:
        propose = KNOWN_TOOLKITS - TOOLKIT_REGISTRY
        if propose:
            propose = ["hyperspy_gui_{}".format(tk) for tk in propose]
            if len(propose) > 1:
                propose_ = ", ".join(propose[:-1])
                propose = propose_ + " and/or {}".format(propose[-1])
            else:
                propose = propose.pop()
        raise NotImplementedError(
            "There is no user interface registered for this feature."
            "Try installing {}.".format(propose))
    if not display:
        widgets = {}
    available_toolkits = set()
    used_toolkits = set()
    for toolkit, f in UI_REGISTRY[toolkey].items():
        if toolkit in toolkits:
            used_toolkits.add(toolkit)
            thisw = f(obj=self, display=display, **kwargs)
            if not display:
                widgets[toolkit] = thisw
        else:
            available_toolkits.add(toolkit)
    if not used_toolkits and available_toolkits:
        is_or_are = "is" if len(toolkits) == 1 else "are"
        raise NotImplementedError(
            "The {} {} not available for this functionality,try with "
            "the {}.".format(
                _toolkits_to_string(toolkits),
                is_or_are,
                _toolkits_to_string(available_toolkits)))
    if not display:
        return widgets
示例#12
0
def add_marker(self,
               marker,
               plot_on_signal=True,
               plot_marker=True,
               permanent=False,
               plot_signal=True):
    """
    Add a marker to the signal or navigator plot.

    Plot the signal, if not yet plotted

    Parameters
    ----------
    marker : marker object or iterable of marker objects
        The marker or iterable (list, tuple, ...) of markers to add.
        See `plot.markers`. If you want to add a large number of markers,
        add them as an iterable, since this will be much faster.
    plot_on_signal : bool, default True
        If True, add the marker to the signal
        If False, add the marker to the navigator
    plot_marker : bool, default True
        If True, plot the marker.
    permanent : bool, default False
        If False, the marker will only appear in the current
        plot. If True, the marker will be added to the
        metadata.Markers list, and be plotted with plot(plot_markers=True).
        If the signal is saved as a HyperSpy HDF5 file, the markers will be
        stored in the HDF5 signal and be restored when the file is loaded.

    Examples
    --------
    >>> import scipy.misc
    >>> import hyperspy.api as hs
    >>> im = hs.signals.Signal2D(scipy.misc.ascent())
    >>> m = hs.markers.rectangle(x1=150, y1=100, x2=400, y2=400, color='red')
    >>> im.add_marker(m)

    Adding to a 1D signal, where the point will change
    when the navigation index is changed
    >>> import numpy as np
    >>> s = hs.signals.Signal1D(np.random.random((3, 100)))
    >>> marker = hs.markers.point((19, 10, 60), (0.2, 0.5, 0.9))
    >>> s.add_marker(marker, permanent=True, plot_marker=True)
    >>> s.plot(plot_markers=True)

    Add permanent marker
    >>> s = hs.signals.Signal2D(np.random.random((100, 100)))
    >>> marker = hs.markers.point(50, 60)
    >>> s.add_marker(marker, permanent=True, plot_marker=True)
    >>> s.plot(plot_markers=True)

    Add permanent marker which changes with navigation position, and
    do not add it to a current plot
    >>> s = hs.signals.Signal2D(np.random.randint(10, size=(3, 100, 100)))
    >>> marker = hs.markers.point((10, 30, 50), (30, 50, 60), color='red')
    >>> s.add_marker(marker, permanent=True, plot_marker=False)
    >>> s.plot(plot_markers=True)

    Removing a permanent marker
    >>> s = hs.signals.Signal2D(np.random.randint(10, size=(100, 100)))
    >>> marker = hs.markers.point(10, 60, color='red')
    >>> marker.name = "point_marker"
    >>> s.add_marker(marker, permanent=True)
    >>> del s.metadata.Markers.point_marker

    Adding many markers as a list
    >>> from numpy.random import random
    >>> s = hs.signals.Signal2D(np.random.randint(10, size=(100, 100)))
    >>> marker_list = []
    >>> for i in range(100):
    ...     marker = hs.markers.point(random()*100, random()*100, color='red')
    ...     marker_list.append(marker)
    >>> s.add_marker(marker_list, permanent=True)

    """
    if isiterable(marker):
        marker_list = marker
    else:
        marker_list = [marker]
    markers_dict = {}
    if permanent:
        if not self.metadata.has_item('Markers'):
            self.metadata.add_node('Markers')
        marker_object_list = []
        for marker_tuple in list(self.metadata.Markers):
            marker_object_list.append(marker_tuple[1])
        name_list = self.metadata.Markers.keys()
    marker_name_suffix = 1
    for m in marker_list:
        marker_data_shape = m._get_data_shape()
        if (not (len(marker_data_shape) == 0)) and (
                marker_data_shape != self.axes_manager.navigation_shape):
            raise ValueError("Navigation shape of the marker must be 0 or the "
                             "same navigation shape as this signal.")
        if (m.signal is not None) and (m.signal is not self):
            raise ValueError("Markers can not be added to several signals")
        m._plot_on_signal = plot_on_signal
        if plot_marker:
            if self._plot is None:
                self.plot()
            if m._plot_on_signal:
                self._plot.signal_plot.add_marker(m)
            else:
                if self._plot.navigator_plot is None:
                    self.plot()
                self._plot.navigator_plot.add_marker(m)
            m.plot(update_plot=False)
        if permanent:
            for marker_object in marker_object_list:
                if m is marker_object:
                    raise ValueError("Marker already added to signal")
            name = m.name
            temp_name = name
            while temp_name in name_list:
                temp_name = name + str(marker_name_suffix)
                marker_name_suffix += 1
            m.name = temp_name
            markers_dict[m.name] = m
            m.signal = self
            marker_object_list.append(m)
            name_list.append(m.name)
    if permanent:
        self.metadata.Markers = markers_dict
    if plot_marker:
        if self._plot.signal_plot:
            self._plot.signal_plot.ax.hspy_fig._draw_animated()
        if self._plot.navigator_plot:
            self._plot.navigator_plot.ax.hspy_fig._draw_animated()
示例#13
0
    def add_atom_list(
            self, x, y, sigma_x=1, sigma_y=1, amplitude=1, rotation=0):
        """
        Add several atoms to the test data.

        Parameters
        ----------
        x, y : iterable
            Position of the atoms. Must be iterable, and have the same size.
        sigma_x, sigma_y : number or iterable, default 1
            If number: all the atoms will have the same sigma.
            Use iterable for setting different sigmas for different atoms.
            If iterable: must be same length as x and y iterables.
        amplitude : number or iterable, default 1
            If number: all the atoms will have the same amplitude.
            Use iterable for setting different amplitude for different atoms.
            If iterable: must be same length as x and y iterables.
        rotation : number or iterable, default 0
            If number: all the atoms will have the same rotation.
            Use iterable for setting different rotation for different atoms.
            If iterable: must be same length as x and y iterables.

        Examples
        --------
        >>> from temul.external.atomap_devel_012.testing_tools import MakeTestData
        >>> test_data = MakeTestData(200, 200)
        >>> import numpy as np
        >>> x, y = np.mgrid[0:200:10j, 0:200:10j]
        >>> x, y = x.flatten(), y.flatten()
        >>> test_data.add_atom_list(x, y)
        >>> test_data.signal.plot()

        """
        if len(x) != len(y):
            raise ValueError("x and y needs to have the same length")

        if isiterable(sigma_x):
            if len(sigma_x) != len(x):
                raise ValueError("sigma_x and x needs to have the same length")
        else:
            sigma_x = [sigma_x] * len(x)

        if isiterable(sigma_y):
            if len(sigma_y) != len(y):
                raise ValueError("sigma_y and x needs to have the same length")
        else:
            sigma_y = [sigma_y] * len(x)

        if isiterable(amplitude):
            if len(amplitude) != len(x):
                raise ValueError(
                    "amplitude and x needs to have the same length")
        else:
            amplitude = [amplitude] * len(x)

        if isiterable(rotation):
            if len(rotation) != len(x):
                raise ValueError(
                    "rotation and x needs to have the same length")
        else:
            rotation = [rotation] * len(x)
        iterator = zip(x, y, sigma_x, sigma_y, amplitude, rotation)
        for tx, ty, tsigma_x, tsigma_y, tamplitude, trotation in iterator:
            self.add_atom(tx, ty, tsigma_x, tsigma_y, tamplitude, trotation)
示例#14
0
def get_gui(self, toolkey, display=True, toolkit=None, **kwargs):
    if not TOOLKIT_REGISTRY:
        raise ImportError(
            "No toolkit registered. Install hyperspy_gui_ipywidgets or "
            "hyperspy_gui_traitsui GUI elements.")
    from hyperspy.defaults_parser import preferences
    if isinstance(toolkit, str):
        toolkit = (toolkit, )
    if isiterable(toolkit):
        toolkits = set()
        for tk in toolkit:
            if tk in TOOLKIT_REGISTRY:
                toolkits.add(tk)
            else:
                raise ValueError(f"{tk} is not a registered toolkit.")
    elif toolkit is None:
        toolkits = set()
        available_disabled_toolkits = set()
        if "ipywidgets" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_ipywidgets_gui:
                toolkits.add("ipywidgets")
            else:
                available_disabled_toolkits.add("ipywidgets")
        if "traitsui" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_traitsui_gui:
                toolkits.add("traitsui")
            else:
                available_disabled_toolkits.add("traitsui")
        if not toolkits and available_disabled_toolkits:
            is_or_are = "is" if len(
                available_disabled_toolkits) == 1 else "are"
            them_or_it = ("it"
                          if len(available_disabled_toolkits) == 1 else "them")
            raise ValueError(
                "No toolkit available. The "
                f"{_toolkits_to_string(available_disabled_toolkits)} "
                f"{is_or_are} installed but disabled in `preferences`. "
                f"Enable {them_or_it} in `preferences` or "
                "manually select a toolkit with the `toolkit` argument.")

    else:
        raise ValueError(
            "`toolkit` must be a string, an iterable of strings or None.")
    if toolkey not in UI_REGISTRY or not UI_REGISTRY[toolkey]:
        propose = KNOWN_TOOLKITS - TOOLKIT_REGISTRY
        if propose:
            propose = [f"hyperspy_gui_{tk}" for tk in propose]
            if len(propose) > 1:
                propose_ = ", ".join(propose[:-1])
                propose = f"{propose_} and/or {propose[-1]}"
            else:
                propose = propose.pop()
        raise NotImplementedError(
            "There is no user interface registered for this feature."
            f"Try installing {propose}.")
    if not display:
        widgets = {}
    available_toolkits = set()
    used_toolkits = set()
    for toolkit, specs in UI_REGISTRY[toolkey].items():
        f = getattr(importlib.import_module(specs["module"]),
                    specs["function"])
        if toolkit in toolkits:
            used_toolkits.add(toolkit)
            try:
                thisw = f(obj=self, display=display, **kwargs)
            except NotImplementedError as e:
                # traitsui raises this exception when the backend is
                # not supported
                if toolkit == "traitsui":
                    pass
                else:
                    raise e
            if not display:
                widgets[toolkit] = thisw
        else:
            available_toolkits.add(toolkit)
    if not used_toolkits and available_toolkits:
        is_or_are = "is" if len(toolkits) == 1 else "are"
        raise NotImplementedError(
            f"The {_toolkits_to_string(toolkits)} {is_or_are} not available "
            "for this functionality, try with the "
            f"{_toolkits_to_string(available_toolkits)}.")
    if not display:
        return widgets
示例#15
0
    def get_probe_area(self, navigation_axes=None):
        """
        Calculates a pixel area which can be approximated to probe area,
        when the beam is larger than or equal to pixel size.
        The probe area can be calculated only when the number of navigation
        dimension are less than 2 and all the units have the dimensions of
        length.

        Parameters
        ----------
        navigation_axes : DataAxis, string or integer (or list of)
            Navigation axes corresponding to the probe area. If string or
            integer, the provided value is used to index the ``axes_manager``.

        Returns
        -------
        probe area in nm².

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_TEM_Spectrum()
        >>> si = hs.stack([s]*3)
        >>> si.axes_manager.navigation_axes[0].scale = 0.01
        >>> si.axes_manager.navigation_axes[0].units = 'μm'
        >>> si.get_probe_area()
        100.0

        """
        if navigation_axes is None:
            navigation_axes = self.axes_manager.navigation_axes
        elif not isiterable(navigation_axes):
            navigation_axes = [navigation_axes]
        if len(navigation_axes) == 0:
            raise ValueError("The navigation dimension is zero, the probe "
                             "area can not be calculated automatically.")
        elif len(navigation_axes) > 2:
            raise ValueError("The navigation axes corresponding to the probe "
                             "are ambiguous and the probe area can not be "
                             "calculated automatically.")
        scales = []

        for axis in navigation_axes:
            try:
                if not isinstance(navigation_axes, DataAxis):
                    axis = self.axes_manager[axis]
                scales.append(axis.convert_to_units('nm', inplace=False)[0])
            except pint.DimensionalityError:
                raise ValueError(f"The unit of the axis {axis} has not the "
                                 "dimension of length.")

        if len(scales) == 1:
            probe_area = scales[0]**2
        else:
            probe_area = scales[0] * scales[1]

        if probe_area == 1:
            warnings.warn(
                "Please note that the probe area has been "
                "calculated to be 1 nm², meaning that it is highly "
                "likley that the scale of the navigation axes have not "
                "been set correctly. Please read the user "
                "guide for how to set this.")
        return probe_area
示例#16
0
def get_gui(self, toolkey, display=True, toolkit=None, **kwargs):
    if not TOOLKIT_REGISTRY:
        raise ImportError(
            "No toolkit registered. Install hyperspy_gui_ipywidgets or "
            "hyperspy_gui_traitsui GUI elements. If hyperspy_gui_traits"
            "is installed, initialize a toolkit supported by traitsui "
            "before importing HyperSpy."
        )
    from hyperspy.defaults_parser import preferences
    if isinstance(toolkit, str):
        toolkit = (toolkit,)
    if isiterable(toolkit):
        toolkits = set()
        for tk in toolkit:
            if tk in TOOLKIT_REGISTRY:
                toolkits.add(tk)
            else:
                raise ValueError(
                    "{} is not a registered toolkit.".format(tk)
                )
    elif toolkit is None:
        toolkits = set()
        available_disabled_toolkits = set()
        if "ipywidgets" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_ipywidgets_gui:
                toolkits.add("ipywidgets")
            else:
                available_disabled_toolkits.add("ipywidgets")
        if "traitsui" in TOOLKIT_REGISTRY:
            if preferences.GUIs.enable_traitsui_gui:
                toolkits.add("traitsui")
            else:
                available_disabled_toolkits.add("traitsui")
        if not toolkits and available_disabled_toolkits:
            is_or_are = "is" if len(
                available_disabled_toolkits) == 1 else "are"
            them_or_it = ("it" if len(available_disabled_toolkits) == 1
                          else "them")
            raise ValueError(
                "No toolkit available. The {} {} installed but "
                "disabled in `preferences`. Enable {} in `preferences` or "
                "manually select a toolkit with the `toolkit` argument.".format(
                    _toolkits_to_string(available_disabled_toolkits),
                    is_or_are, them_or_it)
            )

    else:
        raise ValueError(
            "`toolkit` must be a string, an iterable of strings or None.")
    if toolkey not in UI_REGISTRY or not UI_REGISTRY[toolkey]:
        propose = KNOWN_TOOLKITS - TOOLKIT_REGISTRY
        if propose:
            propose = ["hyperspy_gui_{}".format(tk) for tk in propose]
            if len(propose) > 1:
                propose_ = ", ".join(propose[:-1])
                propose = propose_ + " and/or {}".format(propose[-1])
            else:
                propose = propose.pop()
        raise NotImplementedError(
            "There is no user interface registered for this feature."
            "Try installing {}.".format(propose))
    if not display:
        widgets = {}
    available_toolkits = set()
    used_toolkits = set()
    for toolkit, f in UI_REGISTRY[toolkey].items():
        if toolkit in toolkits:
            used_toolkits.add(toolkit)
            thisw = f(obj=self, display=display, **kwargs)
            if not display:
                widgets[toolkit] = thisw
        else:
            available_toolkits.add(toolkit)
    if not used_toolkits and available_toolkits:
        is_or_are = "is" if len(toolkits) == 1 else "are"
        raise NotImplementedError(
            "The {} {} not available for this functionality,try with "
            "the {}.".format(
                _toolkits_to_string(toolkits),
                is_or_are,
                _toolkits_to_string(available_toolkits)))
    if not display:
        return widgets
示例#17
0
def get_ellipse_model_ransac(
    data,
    xf=128,
    yf=128,
    rf_lim=30,
    semi_len_min=70,
    semi_len_max=90,
    semi_len_ratio_lim=1.2,
    min_samples=6,
    residual_threshold=10,
    max_trails=500,
    show_progressbar=True,
):
    """Pick a random number of data points to fit an ellipse to.

    The ellipse's constraints can be specified.

    See skimage.measure.ransac for more information.

    Parameters
    ----------
    data : NumPy array
        In the form [[[[x0, y0], [x1, y1], ...]]]
    xf, yf : scalar, optional
        Default 128
    rf_lim : scalar, optional
        How far the ellipse centre can be from (xf, yf)
    semi_len_min, semi_len_max : scalar, optional
        Limits of the semi lengths
    semi_len_ratio_lim : scalar, optional
        Limit of the ratio of the semi length, must be equal or larger
        than 1. This ratio is calculated by taking the largest semi length
        divided by the smallest semi length:
        max(semi0, semi1)/min(semi0, semi1). So for a perfect circle this
        ratio will be 1.
    min_samples : scalar, optional
        Minimum number of data points to fit the ellipse model to.
    residual_threshold : scalar, optional
        Maximum distance for a data point to be considered an inlier.
    max_trails : scalar, optional
        Maximum number of tries for the ransac algorithm.
    show_progressbar : bool, optional
        Default True

    Returns
    -------
    ellipse_array, inlier_array : NumPy array
        Model data is accessed in ellipse_array, where each probe position
        (for two axes) contain a list with the ellipse parameters:
        [y, x, semi_len0, semi_len1, rotation]. If no ellipse is found
        this is None.

    """
    if not isiterable(xf):
        xf = np.ones(data.shape[:2]) * xf
    if not isiterable(yf):
        yf = np.ones(data.shape[:2]) * yf

    ellipse_array = np.zeros(data.shape[:2], dtype=object)
    inlier_array = np.zeros(data.shape[:2], dtype=object)
    num_total = data.shape[0] * data.shape[1]
    t = tqdm(np.ndindex(data.shape[:2]),
             disable=not show_progressbar,
             total=num_total)
    for iy, ix in t:
        temp_xf, temp_yf = xf[iy, ix], yf[iy, ix]
        ellipse_model, inliers = get_ellipse_model_ransac_single_frame(
            data[iy, ix],
            xf=temp_yf,
            yf=temp_xf,
            rf_lim=rf_lim,
            semi_len_min=semi_len_min,
            semi_len_max=semi_len_max,
            semi_len_ratio_lim=semi_len_ratio_lim,
            min_samples=min_samples,
            residual_threshold=residual_threshold,
            max_trails=max_trails,
        )
        if ellipse_model is not None:
            params = ellipse_model.params
        else:
            params = None
        ellipse_array[iy, ix] = params
        inlier_array[iy, ix] = inliers
    return ellipse_array, inlier_array
示例#18
0
def generate_4d_data(
    probe_size_x=10,
    probe_size_y=10,
    image_size_x=50,
    image_size_y=50,
    disk_x=25,
    disk_y=25,
    disk_r=5,
    disk_I=20,
    ring_x=25,
    ring_y=25,
    ring_r=20,
    ring_I=6,
    ring_lw=0,
    ring_e_x=None,
    ring_e_y=25,
    ring_e_semi_len0=15,
    ring_e_semi_len1=15,
    ring_e_r=0,
    ring_e_I=6,
    ring_e_lw=1,
    blur=True,
    blur_sigma=1,
    downscale=True,
    add_noise=False,
    noise_amplitude=1,
    lazy=False,
    lazy_chunks=None,
    show_progressbar=True,
):
    """Generate a test dataset containing a disk and diffraction ring.

    Useful for checking that radial average algorithms are working
    properly.

    The centre, intensity and radius position of the ring and disk can vary
    as a function of probe position, through the disk_x, disk_y, disk_r,
    disk_I, ring_x, ring_y, ring_r and ring_I arguments.
    In addition, the line width of the ring can be varied with ring_lw.

    There is also an elliptical ring, which can be added separately
    to the circular ring. This elliptical ring uses the ring_e_*
    arguments. It is disabled by default.

    The ring can be deactivated by setting ring_x=None.
    The disk can be deactivated by setting disk_x=None.
    The elliptical ring can be deactivated by setting ring_e_x=None.

    Parameters
    ----------
    probe_size_x, probe_size_y : int, default 10
        Size of the navigation dimension.
    image_size_x, image_size_y : int, default 50
        Size of the signal dimension.
    disk_x, disk_y : int or NumPy 2D-array, default 20
        Centre position of the disk. Either integer or NumPy 2-D array.
        See examples on how to make them the correct size.
        To deactivate the disk, set disk_x=None.
    disk_r : int or NumPy 2D-array, default 5
        Radius of the disk. Either integer or NumPy 2-D array.
        See examples on how to make it the correct size.
    disk_I : int or NumPy 2D-array, default 20
        Intensity of the disk, for each of the pixels.
        So if I=30, the each pixel in the disk will have a value of 30.
        Note, this value will change if blur=True or downscale=True.
    ring_x, ring_y : int or NumPy 2D-array, default 20
        Centre position of the ring. Either integer or NumPy 2-D array.
        See examples on how to make them the correct size.
        To deactivate the ring, set ring_x=None.
    ring_r : int or NumPy 2D-array, default 20
        Radius of the ring. Either integer or NumPy 2-D array.
        See examples on how to make it the correct size.
    ring_I : int or NumPy 2D-array, default 6
        Intensity of the ring, for each of the pixels.
        So if I=5, each pixel in the ring will have a value of 5.
        Note, this value will change if blur=True or downscale=True.
    ring_lw : int or NumPy 2D-array, default 0
        Line width of the ring. If ring_lw=1, the line will be 3 pixels wide.
        If ring_lw=2, the line will be 5 pixels wide.
    ring_e_x, ring_e_y : int or NumPy 2D-array, default 20
        Centre position of the elliptical ring. Either integer or
        NumPy 2-D array. See examples on how to make them the correct size.
        To deactivate the ring, set ring_x=None (which is the default).
    ring_e_semi_len0, ring_e_semi_len1 : int or NumPy 2D-array, default 15
        Semi lengths of the elliptical ring. Either integer or NumPy 2-D
        arrays. See examples on how to make it the correct size.
    ring_e_I : int or NumPy 2D-array, default 6
        Intensity of the elliptical ring, for each of the pixels.
        So if I=5, each pixel in the ring will have a value of 5.
        Note, this value will change if blur=True or downscale=True.
    ring_e_r : int or NumPy 2D-array, default 0
        Rotation of the elliptical ring, in radians.
    ring_e_lw : int or NumPy 2D-array, default 0
        Line width of the ring. If ring_lw=1, the line will be 3 pixels wide.
        If ring_lw=2, the line will be 5 pixels wide.
    blur : bool, default True
        If True, do a Gaussian blur of the disk.
    blur_sigma : int, default 1
        Sigma of the Gaussian blurring, if blur is True.
    downscale : bool, default True
        If True, use upscaling (then downscaling) to anti-alise the disk.
    add_noise : bool, default False
        Add Gaussian random noise.
    noise_amplitude : float, default 1
        The amplitude of the noise, if add_noise is True.
    lazy : bool, default False
        If True, the signal will be lazy
    lazy_chunks : tuple, optional
        Used if lazy is True, default (10, 10, 10, 10).

    Returns
    -------
    signal : HyperSpy Signal2D
        Signal with 2 navigation dimensions and 2 signal dimensions.

    Examples
    --------
    >>> from pyxem.dummy_data import make_diffraction_test_data as mdtd
    >>> s = mdtd.generate_4d_data(show_progressbar=False)
    >>> s.plot()

    Using more arguments

    >>> s = mdtd.generate_4d_data(probe_size_x=20, probe_size_y=30,
    ...         image_size_x=50, image_size_y=90,
    ...         disk_x=30, disk_y=70, disk_r=9, disk_I=30,
    ...         ring_x=35, ring_y=65, ring_r=20, ring_I=10,
    ...         blur=False, downscale=False, show_progressbar=False)

    Adding some Gaussian random noise

    >>> s = mdtd.generate_4d_data(add_noise=True, noise_amplitude=3,
    ...         show_progressbar=False)

    Different centre positions for each probe position.
    Note the size=(20, 10), and probe_x=10, probe_y=20: size=(y, x).

    >>> import numpy as np
    >>> disk_x = np.random.randint(5, 35, size=(20, 10))
    >>> disk_y = np.random.randint(5, 45, size=(20, 10))
    >>> disk_I = np.random.randint(50, 100, size=(20, 10))
    >>> ring_x = np.random.randint(5, 35, size=(20, 10))
    >>> ring_y = np.random.randint(5, 45, size=(20, 10))
    >>> ring_r = np.random.randint(10, 15, size=(20, 10))
    >>> ring_I = np.random.randint(1, 30, size=(20, 10))
    >>> ring_lw = np.random.randint(1, 5, size=(20, 10))
    >>> s = mdtd.generate_4d_data(probe_size_x=10, probe_size_y=20,
    ...         image_size_x=40, image_size_y=50, disk_x=disk_x, disk_y=disk_y,
    ...         disk_I=disk_I, ring_x=ring_x, ring_y=ring_y, ring_r=ring_r,
    ...         ring_I=ring_I, ring_lw=ring_lw, show_progressbar=False)

    Do not plot the disk

    >>> s = mdtd.generate_4d_data(disk_x=None, show_progressbar=False)

    Do not plot the ring

    >>> s = mdtd.generate_4d_data(ring_x=None, show_progressbar=False)

    Plot only an elliptical ring

    >>> from numpy.random import randint, random
    >>> s = mdtd.generate_4d_data(
    ...        probe_size_x=10, probe_size_y=10,
    ...        disk_x=None, ring_x=None,
    ...        ring_e_x=randint(20, 30, (10, 10)),
    ...        ring_e_y=randint(20, 30, (10, 10)),
    ...        ring_e_semi_len0=randint(10, 20, (10, 10)),
    ...        ring_e_semi_len1=randint(10, 20, (10, 10)),
    ...        ring_e_r=random((10, 10))*np.pi,
    ...        ring_e_lw=randint(1, 3, (10, 10)))

    """
    if disk_x is None:
        plot_disk = False
    else:
        plot_disk = True
        if not isiterable(disk_x):
            disk_x = np.ones((probe_size_y, probe_size_x)) * disk_x
    if not isiterable(disk_y):
        disk_y = np.ones((probe_size_y, probe_size_x)) * disk_y
    if not isiterable(disk_r):
        disk_r = np.ones((probe_size_y, probe_size_x)) * disk_r
    if not isiterable(disk_I):
        disk_I = np.ones((probe_size_y, probe_size_x)) * disk_I

    if ring_x is None:
        plot_ring = False
    else:
        plot_ring = True
        if not isiterable(ring_x):
            ring_x = np.ones((probe_size_y, probe_size_x)) * ring_x
    if not isiterable(ring_y):
        ring_y = np.ones((probe_size_y, probe_size_x)) * ring_y
    if not isiterable(ring_r):
        ring_r = np.ones((probe_size_y, probe_size_x)) * ring_r
    if not isiterable(ring_I):
        ring_I = np.ones((probe_size_y, probe_size_x)) * ring_I
    if not isiterable(ring_lw):
        ring_lw = np.ones((probe_size_y, probe_size_x)) * ring_lw

    if ring_e_x is None:
        plot_ring_e = False
    else:
        plot_ring_e = True
        if not isiterable(ring_e_x):
            ring_e_x = np.ones((probe_size_y, probe_size_x)) * ring_e_x
    if not isiterable(ring_e_y):
        ring_e_y = np.ones((probe_size_y, probe_size_x)) * ring_e_y
    if not isiterable(ring_e_semi_len0):
        ring_e_semi_len0 = np.ones((probe_size_y, probe_size_x)) * ring_e_semi_len0
    if not isiterable(ring_e_semi_len1):
        ring_e_semi_len1 = np.ones((probe_size_y, probe_size_x)) * ring_e_semi_len1
    if not isiterable(ring_e_I):
        ring_e_I = np.ones((probe_size_y, probe_size_x)) * ring_e_I
    if not isiterable(ring_e_lw):
        ring_e_lw = np.ones((probe_size_y, probe_size_x)) * ring_e_lw
    if not isiterable(ring_e_r):
        ring_e_r = np.ones((probe_size_y, probe_size_x)) * ring_e_r

    signal_shape = (probe_size_y, probe_size_x, image_size_y, image_size_x)
    s = Diffraction2D(np.zeros(shape=signal_shape))
    for i in tqdm(s, desc="Make test data", disable=not show_progressbar):
        index = s.axes_manager.indices[::-1]
        test_data = MakeTestData(
            size_x=image_size_x,
            size_y=image_size_y,
            default=False,
            blur=blur,
            blur_sigma=blur_sigma,
            downscale=downscale,
        )
        if plot_disk:
            dx, dy, dr = disk_x[index], disk_y[index], disk_r[index]
            dI = disk_I[index]
            test_data.add_disk(dx, dy, dr, intensity=dI)
        if plot_ring:
            rx, ry, rr = ring_x[index], ring_y[index], ring_r[index]
            rI, rLW = ring_I[index], ring_lw[index]
            test_data.add_ring(rx, ry, rr, intensity=rI, lw_pix=rLW)
        if plot_ring_e:
            rex, rey = ring_e_x[index], ring_e_y[index]
            resl0, resl1 = ring_e_semi_len0[index], ring_e_semi_len1[index]
            reI, reLW, rer = ring_e_I[index], ring_e_lw[index], ring_e_r[index]
            test_data.add_ring_ellipse(
                x0=rex,
                y0=rey,
                semi_len0=resl0,
                semi_len1=resl1,
                rotation=rer,
                intensity=reI,
                lw_r=reLW,
            )
        s.data[index][:] = test_data.signal.data[:]
        if add_noise:
            s.data[index][:] += (
                np.random.random(size=(image_size_y, image_size_x)) * noise_amplitude
            )
    s.axes_manager.indices = [0] * s.axes_manager.navigation_dimension
    if lazy:
        if lazy_chunks is None:
            lazy_chunks = 10, 10, 10, 10
        data_lazy = da.from_array(s.data, lazy_chunks)
        s = LazyDiffraction2D(data_lazy)
    return s
示例#19
0
def fit_ellipses_to_signal(s,
                           radial_signal_span_list,
                           prepeak_range=None,
                           angleN=20,
                           show_progressbar=True):
    """
    Parameters
    ----------
    s : HyperSpy Signal2D
    radial_signal_span_list : tuple
    prepeak_range : tuple, optional
    angleN : list or int, default 20
    show_progressbar : bool, default True

    Returns
    -------
    signal : HyperSpy 2D signal
        Fitted ellipse and fitting points are stored as HyperSpy markers
        in the metadata
    xC, yC : floats
        Centre position
    semi_len0, semi_len1 : floats
        Length of the two semi-axes.
    rot : float
        Angle between semi_len0 and the positive x-axis. Since semi_len0,
        is not necessarily the longest semi-axis, the rotation will _not_ be
        between the major semi-axis and the positive x-axis.
        In radians, between 0 and pi. The rotation is clockwise, so
        at rot = 0.1 the ellipse will be pointing in the positive x-direction,
        and negative y-direction.
    eccen : float
        Eccentricity of the ellipse

    Examples
    --------
    >>> import pyxem.dummy_data import make_diffraction_test_data as mdtd
    >>> s = ps.PixelatedSTEM(np.zeros((200, 220)))
    >>> s.axes_manager[0].offset, s.axes_manager[1].offset = -100, -110
    >>> xx, yy = np.meshgrid(s.axes_manager[0].axis, s.axes_manager[1].axis)
    >>> ellipse_ring = mdtd._get_elliptical_ring(xx, yy, 0, 0, 50, 70, 0.8)
    >>> s.data += ellipse_ring
    >>> from pyxem..utils.radial_tools import fit_ellipses_to_signal
    >>> output = fit_ellipses_to_signal(
    ...     s, [(40, 80)], angleN=30, show_progressbar=False)

    """
    if not isiterable(angleN):
        angleN = [angleN] * len(radial_signal_span_list)
    else:
        if len(angleN) != len(radial_signal_span_list):
            raise ValueError(
                "angleN and radial_signal_span_list needs to have "
                "the same length")
    marker_list = []
    ellipse_list = []
    for i, (radial_signal_span,
            aN) in enumerate(zip(radial_signal_span_list, angleN)):
        s_ra = get_radius_vs_angle(
            s,
            radial_signal_span,
            angleN=aN,
            prepeak_range=prepeak_range,
            show_progressbar=show_progressbar,
        )
        x, y = _get_xy_points_from_radius_angle_plot(s_ra)
        ellipse_parameters = _fit_ellipse_to_xy_points(x, y)
        output = _get_ellipse_parameters(ellipse_parameters)
        ellipse_list.append(output)
        marker_list.extend(
            _get_marker_list(ellipse_parameters,
                             x_list=x,
                             y_list=y,
                             name="circle" + str(i)))
    s_m = s.deepcopy()
    s_m.add_marker(marker_list, permanent=True, plot_marker=False)
    return s_m, ellipse_list
示例#20
0
    def compute_navigator(self,
                          index=None,
                          chunks_number=None,
                          show_progressbar=None):
        """
        Compute the navigator by taking the sum over a single chunk contained
        the specified coordinate. Taking the sum over a single chunk is a
        computationally efficient approach to compute the navigator. The data
        can be rechunk by specifying the ``chunks_number`` argument.

        Parameters
        ----------
        index : (int, float, None) or iterable, optional
            Specified where to take the sum, follows HyperSpy indexing syntax
            for integer and float. If None, the index is the centre of the
            signal_space
        chunks_number : (int, None) or iterable, optional
            Define the number of chunks in the signal space used for rechunk
            the when calculating of the navigator. Useful to define the range
            over which the sum is calculated.
            If None, the existing chunking will be considered when picking the
            chunk used in the navigator calculation.
        %s

        Returns
        -------
        None.

        Note
        ----
        The number of chunks will affect where the sum is taken. If the sum
        needs to be taken in the centre of the signal space (for example, in
        the case of diffraction pattern), the number of chunk needs to be an
        odd number, so that the middle is centered.

        """

        signal_shape = self.axes_manager.signal_shape

        if index is None:
            index = [round(shape / 2) for shape in signal_shape]
        else:
            if not isiterable(index):
                index = [index] * len(signal_shape)
            index = [
                axis._get_index(_idx)
                for _idx, axis in zip(index, self.axes_manager.signal_axes)
            ]
        _logger.info(f"Using index: {index}")

        if chunks_number is None:
            chunks = self.data.chunks
        else:
            if not isiterable(chunks_number):
                chunks_number = [chunks_number] * len(signal_shape)
            # Determine the chunk size
            signal_chunks = da.core.normalize_chunks([
                int(size / cn) for cn, size in zip(chunks_number, signal_shape)
            ],
                                                     shape=signal_shape)
            # Needs to reverse the chunks list to match dask chunking order
            signal_chunks = list(signal_chunks)[::-1]
            navigation_chunks = ['auto'] * len(
                self.axes_manager.navigation_shape)
            if LooseVersion(dask.__version__) >= LooseVersion("2.30.0"):
                kwargs = {'balance': True}
            else:
                kwargs = {}
            chunks = self.data.rechunk([*navigation_chunks, *signal_chunks],
                                       **kwargs).chunks

        # Get the slice of the corresponding chunk
        signal_size = len(signal_shape)
        signal_chunks = tuple(chunks[i - signal_size]
                              for i in range(signal_size))
        _logger.info(f"Signal chunks: {signal_chunks}")
        isig_slice = get_signal_chunk_slice(index, chunks)

        _logger.info(f'Computing sum over signal dimension: {isig_slice}')
        axes = [axis.index_in_array for axis in self.axes_manager.signal_axes]
        navigator = self.isig[isig_slice].sum(axes)
        navigator.compute(show_progressbar=show_progressbar)
        navigator.original_metadata.set_item('sum_from', isig_slice)

        self.navigator = navigator.T