예제 #1
0
def stack(signal_list,
          axis=None,
          new_axis_name='stack_element',
          lazy=None,
          **kwargs):
    """Concatenate the signals in the list over a given axis or a new axis.

    The title is set to that of the first signal in the list.

    Parameters
    ----------
    signal_list : list of BaseSignal instances
    axis : {None, int, str}
        If None, the signals are stacked over a new axis. The data must
        have the same dimensions. Otherwise the
        signals are stacked over the axis given by its integer index or
        its name. The data must have the same shape, except in the dimension
        corresponding to `axis`.
    new_axis_name : string
        The name of the new axis when `axis` is None.
        If an axis with this name already
        exists it automatically append '-i', where `i` are integers,
        until it finds a name that is not yet in use.
    lazy: {bool, None}
        Returns a LazySignal if True. If None, only returns lazy rezult if at
        least one is lazy.

    Returns
    -------
    signal : BaseSignal instance (or subclass, determined by the objects in
        signal list)

    Examples
    --------
    >>> data = np.arange(20)
    >>> s = hs.stack([hs.signals.Signal1D(data[:10]),
    ...               hs.signals.Signal1D(data[10:])])
    >>> s
    <Signal1D, title: Stack of , dimensions: (2, 10)>
    >>> s.data
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

    """
    from hyperspy.signals import BaseSignal
    import dask.array as da
    from numbers import Number
    # TODO: remove next time
    deprecated = ['mmap', 'mmap_dir']
    warn_str = "'{}' argument is deprecated, please use 'lazy' instead"
    for k in deprecated:
        if k in kwargs:
            lazy = True
            warnings.warn(warn_str.format(k), VisibleDeprecationWarning)

    axis_input = copy.deepcopy(axis)
    signal_list = list(signal_list)
    # Get the real signal with the most axes to get metadata/class/etc
    # first = sorted(filter(lambda _s: isinstance(_s, BaseSignal), signal_list),
    #                key=lambda _s: _s.data.ndim)[-1]
    first = next(filter(lambda _s: isinstance(_s, BaseSignal), signal_list))

    # Cast numbers as signals. Will broadcast later

    for i, _s in enumerate(signal_list):
        if isinstance(_s, BaseSignal):
            pass
        elif isinstance(_s, Number):
            sig = BaseSignal(_s)
            signal_list[i] = sig
        else:
            raise ValueError("{} type cannot be stacked.".format(type(_s)))

    if lazy is None:
        lazy = any(_s._lazy for _s in signal_list)
    if not isinstance(lazy, bool):
        raise ValueError("'lazy' argument has to be None, True or False")

    # Cast all as lazy if required
    for i, _s in enumerate(signal_list):
        if not _s._lazy:
            signal_list[i] = _s.as_lazy()
    if len(signal_list) > 1:
        newlist = broadcast_signals(*signal_list, ignore_axis=axis_input)
        if axis is not None:
            step_sizes = [s.axes_manager[axis].size for s in newlist]
            axis = newlist[0].axes_manager[axis]
        datalist = [s.data for s in newlist]
        newdata = da.stack(datalist, axis=0) if axis is None else \
            da.concatenate(datalist, axis=axis.index_in_array)
        if axis_input is None:
            signal = first.__class__(newdata)
            signal._lazy = True
            signal._assign_subclass()
            signal.axes_manager._axes[1:] = copy.deepcopy(
                newlist[0].axes_manager._axes)
            axis_name = new_axis_name
            axis_names = [
                axis_.name for axis_ in signal.axes_manager._axes[1:]
            ]
            j = 1
            while axis_name in axis_names:
                axis_name = new_axis_name + "_%i" % j
                j += 1
            eaxis = signal.axes_manager._axes[0]
            eaxis.name = axis_name
            eaxis.navigate = True  # This triggers _update_parameters
            signal.metadata = copy.deepcopy(first.metadata)
            # Get the title from 1st object
            signal.metadata.General.title = ("Stack of " +
                                             first.metadata.General.title)
            signal.original_metadata = DictionaryTreeBrowser({})
        else:
            signal = newlist[0]._deepcopy_with_new_data(newdata)
            signal._lazy = True
            signal._assign_subclass()
        signal.get_dimensions_from_data()
        signal.original_metadata.add_node('stack_elements')

        for i, obj in enumerate(signal_list):
            signal.original_metadata.stack_elements.add_node('element%i' % i)
            node = signal.original_metadata.stack_elements['element%i' % i]
            node.original_metadata = \
                obj.original_metadata.as_dictionary()
            node.metadata = \
                obj.metadata.as_dictionary()

        if axis_input is None:
            axis_input = signal.axes_manager[-1 + 1j].index_in_axes_manager
            step_sizes = 1

        signal.metadata._HyperSpy.set_item('Stacking_history.axis', axis_input)
        signal.metadata._HyperSpy.set_item('Stacking_history.step_sizes',
                                           step_sizes)
        if np.all([
                s.metadata.has_item('Signal.Noise_properties.variance')
                for s in signal_list
        ]):
            variance = stack([
                s.metadata.Signal.Noise_properties.variance
                for s in signal_list
            ], axis)
            signal.metadata.set_item('Signal.Noise_properties.variance',
                                     variance)
    else:
        signal = signal_list[0]

    # Leave as lazy or compute
    if lazy:
        signal = signal.as_lazy()
    else:
        signal.compute(False)

    return signal
예제 #2
0
파일: utils.py 프로젝트: mstatkus/hyperspy
def stack(signal_list,
          axis=None,
          new_axis_name="stack_element",
          lazy=None,
          show_progressbar=None,
          **kwargs):
    """Concatenate the signals in the list over a given axis or a new axis.

    The title is set to that of the first signal in the list.

    Parameters
    ----------
    signal_list : list of BaseSignal instances
        List of signals to stack.
    axis : {None, int, str}
        If None, the signals are stacked over a new axis. The data must
        have the same dimensions. Otherwise the
        signals are stacked over the axis given by its integer index or
        its name. The data must have the same shape, except in the dimension
        corresponding to `axis`.
    new_axis_name : string
        The name of the new axis when `axis` is None.
        If an axis with this name already
        exists it automatically append '-i', where `i` are integers,
        until it finds a name that is not yet in use.
    lazy : {bool, None}
        Returns a LazySignal if True. If None, only returns lazy result if at
        least one is lazy.
    %s

    Returns
    -------
    signal : BaseSignal instance

    Examples
    --------
    >>> data = np.arange(20)
    >>> s = hs.stack([hs.signals.Signal1D(data[:10]),
    ...               hs.signals.Signal1D(data[10:])])
    >>> s
    <Signal1D, title: Stack of , dimensions: (2, 10)>
    >>> s.data
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

    """
    from hyperspy.signals import BaseSignal
    import dask.array as da
    from numbers import Number

    for k in [k for k in ["mmap", "mmap_dir"] if k in kwargs]:
        lazy = True
        warnings.warn(
            f"'{k}' argument is deprecated and will be removed in "
            "HyperSpy v2.0. Please use 'lazy=True' instead.",
            VisibleDeprecationWarning,
        )

    axis_input = copy.deepcopy(axis)
    signal_list = list(signal_list)

    # Get the real signal with the most axes to get metadata/class/etc
    # first = sorted(filter(lambda _s: isinstance(_s, BaseSignal), signal_list),
    #                key=lambda _s: _s.data.ndim)[-1]
    first = next(filter(lambda _s: isinstance(_s, BaseSignal), signal_list))

    # Cast numbers as signals. Will broadcast later.
    for i, _s in enumerate(signal_list):
        if isinstance(_s, BaseSignal):
            pass
        elif isinstance(_s, Number):
            sig = BaseSignal(_s)
            signal_list[i] = sig
        else:
            raise ValueError(f"Objects of type {type(_s)} cannot be stacked")

    if lazy is None:
        lazy = any(_s._lazy for _s in signal_list)

    if not isinstance(lazy, bool):
        raise ValueError("'lazy' argument has to be None, True or False")

    for i, _s in enumerate(signal_list):
        # Cast all as lazy if required
        if not _s._lazy:
            signal_list[i] = _s.as_lazy()

    if len(signal_list) > 1:
        # Matching axis calibration is checked here
        newlist = broadcast_signals(*signal_list, ignore_axis=axis_input)

        if axis is not None:
            step_sizes = [s.axes_manager[axis].size for s in newlist]
            axis = newlist[0].axes_manager[axis]

        datalist = [s.data for s in newlist]
        newdata = (da.stack(datalist, axis=0) if axis is None else
                   da.concatenate(datalist, axis=axis.index_in_array))
        if axis_input is None:
            signal = first.__class__(newdata)
            signal._lazy = True
            signal._assign_subclass()
            signal.axes_manager._axes[1:] = copy.deepcopy(
                newlist[0].axes_manager._axes)
            axis_name = new_axis_name
            axis_names = [
                axis_.name for axis_ in signal.axes_manager._axes[1:]
            ]
            j = 1
            while axis_name in axis_names:
                axis_name = f"{new_axis_name}_{j}"
                j += 1
            eaxis = signal.axes_manager._axes[0]
            eaxis.name = axis_name
            eaxis.navigate = True  # This triggers _update_parameters
            signal.metadata = copy.deepcopy(first.metadata)
            # Get the title from 1st object
            signal.metadata.General.title = f"Stack of {first.metadata.General.title}"
            signal.original_metadata = DictionaryTreeBrowser({})
        else:
            signal = newlist[0]._deepcopy_with_new_data(newdata)
            signal._lazy = True
            signal._assign_subclass()
        signal.get_dimensions_from_data()
        signal.original_metadata.add_node("stack_elements")

        for i, obj in enumerate(signal_list):
            signal.original_metadata.stack_elements.add_node(f"element{i}")
            node = signal.original_metadata.stack_elements[f"element{i}"]
            node.original_metadata = obj.original_metadata.as_dictionary()
            node.metadata = obj.metadata.as_dictionary()

        if axis_input is None:
            axis_input = signal.axes_manager[-1 + 1j].index_in_axes_manager
            step_sizes = 1

        signal.metadata._HyperSpy.set_item("Stacking_history.axis", axis_input)
        signal.metadata._HyperSpy.set_item("Stacking_history.step_sizes",
                                           step_sizes)
        if np.all([
                s.metadata.has_item("Signal.Noise_properties.variance")
                for s in signal_list
        ]):
            variance = stack([
                s.metadata.Signal.Noise_properties.variance
                for s in signal_list
            ], axis)
            signal.metadata.set_item("Signal.Noise_properties.variance",
                                     variance)
    else:
        signal = signal_list[0]

    # Leave as lazy or compute
    if lazy:
        signal = signal.as_lazy()
    else:
        signal.compute(False, show_progressbar=show_progressbar)

    return signal
예제 #3
0
def test_boardcast_signals_error():
    with pytest.raises(ValueError):
        broadcast_signals([0, 1], [2, 3])
    with pytest.raises(ValueError):
        broadcast_signals(Signal1D([0, 1]))
예제 #4
0
파일: utils.py 프로젝트: woozey/hyperspy
def stack(signal_list, axis=None, new_axis_name='stack_element',
          lazy=None, **kwargs):
    """Concatenate the signals in the list over a given axis or a new axis.

    The title is set to that of the first signal in the list.

    Parameters
    ----------
    signal_list : list of BaseSignal instances
    axis : {None, int, str}
        If None, the signals are stacked over a new axis. The data must
        have the same dimensions. Otherwise the
        signals are stacked over the axis given by its integer index or
        its name. The data must have the same shape, except in the dimension
        corresponding to `axis`.
    new_axis_name : string
        The name of the new axis when `axis` is None.
        If an axis with this name already
        exists it automatically append '-i', where `i` are integers,
        until it finds a name that is not yet in use.
    lazy: {bool, None}
        Returns a LazySignal if True. If None, only returns lazy rezult if at
        least one is lazy.

    Returns
    -------
    signal : BaseSignal instance (or subclass, determined by the objects in
        signal list)

    Examples
    --------
    >>> data = np.arange(20)
    >>> s = hs.stack([hs.signals.Signal1D(data[:10]),
    ...               hs.signals.Signal1D(data[10:])])
    >>> s
    <Signal1D, title: Stack of , dimensions: (2, 10)>
    >>> s.data
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

    """
    from itertools import zip_longest
    from hyperspy.signals import BaseSignal
    import dask.array as da
    from numbers import Number
    # TODO: remove next time
    deprecated = ['mmap', 'mmap_dir']
    warn_str = "'{}' argument is deprecated, please use 'lazy' instead"
    for k in deprecated:
        if k in kwargs:
            lazy = True
            warnings.warn(warn_str.format(k), VisibleDeprecationWarning)

    axis_input = copy.deepcopy(axis)
    signal_list = list(signal_list)
    # Get the real signal with the most axes to get metadata/class/etc
    # first = sorted(filter(lambda _s: isinstance(_s, BaseSignal), signal_list),
    #                key=lambda _s: _s.data.ndim)[-1]
    first = next(filter(lambda _s: isinstance(_s, BaseSignal), signal_list))

    # Cast numbers as signals. Will broadcast later

    for i, _s in enumerate(signal_list):
        if isinstance(_s, BaseSignal):
            pass
        elif isinstance(_s, Number):
            sig = BaseSignal(_s)
            signal_list[i] = sig
        else:
            raise ValueError("{} type cannot be stacked.".format(type(_s)))

    if lazy is None:
        lazy = any(_s._lazy for _s in signal_list)
    if not isinstance(lazy, bool):
        raise ValueError("'lazy' argument has to be None, True or False")

    # Cast all as lazy if required
    for i, _s in enumerate(signal_list):
        if not _s._lazy:
            signal_list[i] = _s.as_lazy()
    if len(signal_list) > 1:
        newlist = broadcast_signals(*signal_list, ignore_axis=axis_input)
        if axis is not None:
            step_sizes = [s.axes_manager[axis].size for s in newlist]
            axis = newlist[0].axes_manager[axis]
        datalist = [s.data for s in newlist]
        newdata = da.stack(datalist, axis=0) if axis is None else \
            da.concatenate(datalist, axis=axis.index_in_array)
        if axis_input is None:
            signal = first.__class__(newdata)
            signal._lazy = True
            signal._assign_subclass()
            signal.axes_manager._axes[1:] = copy.deepcopy(
                newlist[0].axes_manager._axes)
            axis_name = new_axis_name
            axis_names = [
                axis_.name for axis_ in signal.axes_manager._axes[
                    1:]]
            j = 1
            while axis_name in axis_names:
                axis_name = new_axis_name + "_%i" % j
                j += 1
            eaxis = signal.axes_manager._axes[0]
            eaxis.name = axis_name
            eaxis.navigate = True  # This triggers _update_parameters
            signal.metadata = copy.deepcopy(first.metadata)
            # Get the title from 1st object
            signal.metadata.General.title = (
                "Stack of " + first.metadata.General.title)
            signal.original_metadata = DictionaryTreeBrowser({})
        else:
            signal = newlist[0]._deepcopy_with_new_data(newdata)
            signal._lazy = True
            signal._assign_subclass()
        signal.get_dimensions_from_data()
        signal.original_metadata.add_node('stack_elements')

        for i, obj in enumerate(signal_list):
            signal.original_metadata.stack_elements.add_node('element%i' % i)
            node = signal.original_metadata.stack_elements['element%i' % i]
            node.original_metadata = \
                obj.original_metadata.as_dictionary()
            node.metadata = \
                obj.metadata.as_dictionary()

        if axis_input is None:
            axis_input = signal.axes_manager[-1 + 1j].index_in_axes_manager
            step_sizes = 1

        signal.metadata._HyperSpy.set_item('Stacking_history.axis', axis_input)
        signal.metadata._HyperSpy.set_item('Stacking_history.step_sizes',
                                           step_sizes)
        if np.all([
                s.metadata.has_item('Signal.Noise_properties.variance')
                for s in signal_list
        ]):
            variance = stack([
                s.metadata.Signal.Noise_properties.variance for s in signal_list
            ], axis)
            signal.metadata.set_item(
                'Signal.Noise_properties.variance', variance)
    else:
        signal = signal_list[0]

    # Leave as lazy or compute
    if lazy:
        signal = signal.as_lazy()
    else:
        signal.compute(False)

    return signal