Ejemplo n.º 1
0
def estimate_variance_parameters(noisy_signal,
                                 clean_signal,
                                 mask=None,
                                 pol_order=1,
                                 higher_than=None,
                                 return_results=False,
                                 plot_results=True,
                                 weighted=False):
    """Find the scale and offset of the Poissonian noise

    By comparing an SI with its denoised version (i.e. by PCA),
    this plots an
    estimation of the variance as a function of the number of counts
    and fits a
    polynomy to the result.

    Parameters
    ----------
    noisy_SI, clean_SI : spectrum.Spectrum instances
    mask : numpy bool array
        To define the channels that will be used in the calculation.
    pol_order : int
        The order of the polynomy.
    higher_than: float
        To restrict the fit to counts over the given value.

    return_results : Bool

    plot_results : Bool

    Returns
    -------
    Dictionary with the result of a linear fit to estimate the offset
    and scale factor

    """
    fold_back_noisy = unfold_if_multidim(noisy_signal)
    fold_back_clean = unfold_if_multidim(clean_signal)

    # The rest of the code assumes that the first data axis
    # is the navigation axis. We transpose the data if that is not the
    # case.
    ns = (noisy_signal.data.copy()
          if noisy_signal.axes_manager[0].index_in_array == 0 else
          noisy_signal.data.T.copy())
    cs = (clean_signal.data.copy()
          if clean_signal.axes_manager[0].index_in_array == 0 else
          clean_signal.data.T.copy())

    if mask is not None:
        _slice = [
            slice(None),
        ] * len(ns.shape)
        _slice[noisy_signal.axes_manager.signal_axes[0].index_in_array]\
            = ~mask
        ns = ns[_slice]
        cs = cs[_slice]

    results0 = _estimate_gain(ns,
                              cs,
                              weighted=weighted,
                              higher_than=higher_than,
                              plot_results=plot_results,
                              binning=0,
                              pol_order=pol_order)

    results2 = _estimate_gain(ns,
                              cs,
                              weighted=weighted,
                              higher_than=higher_than,
                              plot_results=False,
                              binning=2,
                              pol_order=pol_order)

    c = _estimate_correlation_factor(results0['fit'][0], results2['fit'][0], 4)

    message = ("Gain factor: %.2f\n" % results0['fit'][0] +
               "Gain offset: %.2f\n" % results0['fit'][1] +
               "Correlation factor: %.2f\n" % c)
    is_ok = True
    if hyperspy.defaults_parser.preferences.General.interactive is True:
        is_ok = messagesui.information(message +
                                       "Would you like to store the results?")
    else:
        print message
    if is_ok:
        noisy_signal.metadata.set_item(
            "Signal.Noise_properties.Variance_linear_model.gain_factor",
            results0['fit'][0])
        noisy_signal.metadata.set_item(
            "Signal.Noise_properties.Variance_linear_model.gain_offset",
            results0['fit'][1])
        noisy_signal.metadata.set_item(
            "Signal.Noise_properties.Variance_linear_model.correlation_factor",
            c)
        noisy_signal.metadata.set_item(
            "Signal.Noise_properties.Variance_linear_model.parameters_estimation_method",
            'HyperSpy')

    if fold_back_noisy is True:
        noisy_signal.fold()
    if fold_back_clean is True:
        clean_signal.fold()

    if return_results is True:
        return results0
Ejemplo n.º 2
0
def plot_spectra(
        spectra,
        style='default',
        color=None,
        line_style=None,
        padding=1.,
        legend=None,
        legend_picking=True,
        legend_loc='upper right',
        fig=None,
        ax=None,
        **kwargs):
    """Plot several spectra in the same figure.

    Extra keyword arguments are passed to `matplotlib.figure`.

    Parameters
    ----------
    spectra : iterable object
        Ordered spectra list to plot. If `style` is "cascade" or "mosaic"
        the spectra can have different size and axes.
    style : {'default', 'overlap','cascade', 'mosaic', 'heatmap'}
        The style of the plot. The default is "overlap" and can be
        customized in `preferences`.
    color : matplotlib color or a list of them or `None`
        Sets the color of the lines of the plots (no action on 'heatmap').
        If a list, if its length is less than the number of spectra to plot,
        the colors will be cycled. If `None`, use default matplotlib color cycle.
    line_style: matplotlib line style or a list of them or `None`
        Sets the line style of the plots (no action on 'heatmap').
        The main line style are '-','--','steps','-.',':'.
        If a list, if its length is less than the number of
        spectra to plot, line_style will be cycled. If
        If `None`, use continuous lines, eg: ('-','--','steps','-.',':')
    padding : float, optional, default 0.1
        Option for "cascade". 1 guarantees that there is not overlapping. However,
        in many cases a value between 0 and 1 can produce a tighter plot
        without overlapping. Negative values have the same effect but
        reverse the order of the spectra without reversing the order of the
        colors.
    legend: None or list of str or 'auto'
       If list of string, legend for "cascade" or title for "mosaic" is
       displayed. If 'auto', the title of each spectra (metadata.General.title)
       is used.
    legend_picking: bool
        If true, a spectrum can be toggle on and off by clicking on
        the legended line.
    legend_loc : str or int
        This parameter controls where the legend is placed on the figure;
        see the pyplot.legend docstring for valid values
    fig : matplotlib figure or None
        If None, a default figure will be created. Specifying fig will
        not work for the 'heatmap' style.
    ax : matplotlib ax (subplot) or None
        If None, a default ax will be created. Will not work for 'mosaic'
        or 'heatmap' style.
    **kwargs
        remaining keyword arguments are passed to matplotlib.figure() or
        matplotlib.subplots(). Has no effect on 'heatmap' style.

    Example
    -------
    >>> s = load("some_spectra")
    >>> utils.plot.plot_spectra(s, style='cascade', color='red', padding=0.5)

    To save the plot as a png-file

    >>> utils.plot.plot_spectra(s).figure.savefig("test.png")

    Returns
    -------
    ax: matplotlib axes or list of matplotlib axes
        An array is returned when `style` is "mosaic".

    """
    import hyperspy.signal

    if style == "default":
        style = preferences.Plot.default_style_to_compare_spectra

    if color is not None:
        if hasattr(color, "__iter__"):
            color = itertools.cycle(color)
        elif isinstance(color, basestring):
            color = itertools.cycle([color])
        else:
            raise ValueError("Color must be None, a valid matplotlib color "
                             "string or a list of valid matplotlib colors.")
    else:
        color = itertools.cycle(plt.rcParams['axes.color_cycle'])

    if line_style is not None:
        if hasattr(line_style, "__iter__"):
            line_style = itertools.cycle(line_style)
        elif isinstance(line_style, basestring):
            line_style = itertools.cycle([line_style])
        else:
            raise ValueError("line_style must be None, a valid matplotlib"
                             " line_style string or a list of valid matplotlib"
                             " line_style.")
    else:
        line_style = ['-'] * len(spectra)

    if legend is not None:
        if hasattr(legend, "__iter__"):
            legend = itertools.cycle(legend)
        elif legend == 'auto':
            legend = [spec.metadata.General.title for spec in spectra]
        else:
            raise ValueError("legend must be None, 'auto' or a list of string")

    if style == 'overlap':
        if fig is None:
            fig = plt.figure(**kwargs)
        if ax is None:
            ax = fig.add_subplot(111)
        _make_overlap_plot(spectra,
                           ax,
                           color=color,
                           line_style=line_style,)
        if legend is not None:
            plt.legend(legend, loc=legend_loc)
            if legend_picking is True:
                animate_legend(figure=fig)
    elif style == 'cascade':
        if fig is None:
            fig = plt.figure(**kwargs)
        if ax is None:
            ax = fig.add_subplot(111)
        _make_cascade_subplot(spectra,
                              ax,
                              color=color,
                              line_style=line_style,
                              padding=padding)
        if legend is not None:
            plt.legend(legend, loc=legend_loc)
    elif style == 'mosaic':
        default_fsize = plt.rcParams["figure.figsize"]
        figsize = (default_fsize[0], default_fsize[1] * len(spectra))
        fig, subplots = plt.subplots(
            len(spectra), 1, figsize=figsize, **kwargs)
        if legend is None:
            legend = [legend] * len(spectra)
        for spectrum, ax, color, line_style, legend in zip(spectra,
                                                           subplots, color, line_style, legend):
            _plot_spectrum(spectrum, ax, color=color, line_style=line_style)
            ax.set_ylabel('Intensity')
            if legend is not None:
                ax.set_title(legend)
            if not isinstance(spectra, hyperspy.signal.Signal):
                _set_spectrum_xlabel(spectrum, ax)
        if isinstance(spectra, hyperspy.signal.Signal):
            _set_spectrum_xlabel(spectrum, ax)
        fig.tight_layout()

    elif style == 'heatmap':
        if not isinstance(spectra, hyperspy.signal.Signal):
            import hyperspy.utils
            spectra = hyperspy.utils.stack(spectra)
        refold = unfold_if_multidim(spectra)
        ax = _make_heatmap_subplot(spectra)
        ax.set_ylabel('Spectra')
        if refold is True:
            spectra.fold()
    ax = ax if style != "mosaic" else subplots

    return ax
Ejemplo n.º 3
0
def estimate_variance_parameters(
        noisy_signal,
        clean_signal,
        mask=None,
        pol_order=1,
        higher_than=None,
        return_results=False,
        plot_results=True,
        weighted=False):
    """Find the scale and offset of the Poissonian noise

    By comparing an SI with its denoised version (i.e. by PCA),
    this plots an
    estimation of the variance as a function of the number of counts
    and fits a
    polynomy to the result.

    Parameters
    ----------
    noisy_SI, clean_SI : spectrum.Spectrum instances
    mask : numpy bool array
        To define the channels that will be used in the calculation.
    pol_order : int
        The order of the polynomy.
    higher_than: float
        To restrict the fit to counts over the given value.

    return_results : Bool

    plot_results : Bool

    Returns
    -------
    Dictionary with the result of a linear fit to estimate the offset
    and scale factor

    """
    fold_back_noisy = unfold_if_multidim(noisy_signal)
    fold_back_clean = unfold_if_multidim(clean_signal)

    # The rest of the code assumes that the first data axis
    # is the navigation axis. We transpose the data if that is not the
    # case.
    ns = (noisy_signal.data.copy()
          if noisy_signal.axes_manager[0].index_in_array == 0
          else noisy_signal.data.T.copy())
    cs = (clean_signal.data.copy()
          if clean_signal.axes_manager[0].index_in_array == 0
          else clean_signal.data.T.copy())

    if mask is not None:
        _slice = [slice(None), ] * len(ns.shape)
        _slice[noisy_signal.axes_manager.signal_axes[0].index_in_array]\
            = ~mask
        ns = ns[_slice]
        cs = cs[_slice]

    results0 = _estimate_gain(ns, cs, weighted=weighted,
                              higher_than=higher_than, plot_results=plot_results, binning=0,
                              pol_order=pol_order)

    results2 = _estimate_gain(ns, cs, weighted=weighted,
                              higher_than=higher_than, plot_results=False, binning=2,
                              pol_order=pol_order)

    c = _estimate_correlation_factor(results0['fit'][0],
                                     results2['fit'][0], 4)

    message = ("Gain factor: %.2f\n" % results0['fit'][0] +
               "Gain offset: %.2f\n" % results0['fit'][1] +
               "Correlation factor: %.2f\n" % c)
    is_ok = True
    if hyperspy.defaults_parser.preferences.General.interactive is True:
        is_ok = messagesui.information(
            message + "Would you like to store the results?")
    else:
        print message
    if is_ok:
        noisy_signal.metadata.set_item("Signal.Noise_properties.Variance_linear_model.gain_factor",
                                       results0['fit'][0])
        noisy_signal.metadata.set_item("Signal.Noise_properties.Variance_linear_model.gain_offset",
                                       results0['fit'][1])
        noisy_signal.metadata.set_item("Signal.Noise_properties.Variance_linear_model.correlation_factor",
                                       c)
        noisy_signal.metadata.set_item("Signal.Noise_properties.Variance_linear_model.parameters_estimation_method",
                                       'HyperSpy')

    if fold_back_noisy is True:
        noisy_signal.fold()
    if fold_back_clean is True:
        clean_signal.fold()

    if return_results is True:
        return results0
Ejemplo n.º 4
0
def plot_spectra(
        spectra,
        style='default',
        color=None,
        line_style=None,
        padding=1.,
        legend=None,
        legend_picking=True,
        fig=None,):
    """Plot several spectra in the same figure.

    Extra keyword arguments are passed to `matplotlib.figure`.

    Parameters
    ----------
    spectra : iterable object
        Ordered spectra list to plot. If `style` is "cascade" or "mosaic"
        the spectra can have different size and axes.
    style : {'default', 'overlap','cascade', 'mosaic', 'heatmap'}
        The style of the plot. The default is "overlap" and can be
        customized in `preferences`.
    color : matplotlib color or a list of them or `None`
        Sets the color of the lines of the plots (no action on 'heatmap').
        If a list, if its length is less than the number of spectra to plot,
        the colors will be cycled. If `None`, use default matplotlib color cycle.
    line_style: matplotlib line style or a list of them or `None`
        Sets the line style of the plots (no action on 'heatmap').
        The main line style are '-','--','steps','-.',':'.
        If a list, if its length is less than the number of
        spectra to plot, line_style will be cycled. If
        If `None`, use continuous lines, eg: ('-','--','steps','-.',':')
    padding : float, optional, default 0.1
        Option for "cascade". 1 guarantees that there is not overlapping. However,
        in many cases a value between 0 and 1 can produce a tighter plot
        without overlapping. Negative values have the same effect but
        reverse the order of the spectra without reversing the order of the
        colors.
    legend: None or list of str or 'auto'
       If list of string, legend for "cascade" or title for "mosaic" is
       displayed. If 'auto', the title of each spectra (metadata.General.title)
       is used.
    legend_picking: bool
        If true, a spectrum can be toggle on and off by clicking on
        the legended line.
    fig : matplotlib figure or None
        If None, a default figure will be created. Specifying fig will
        not work for the 'heatmap' style.

    Example
    -------
    >>> s = load("some_spectra")
    >>> utils.plot.plot_spectra(s, style='cascade', color='red', padding=0.5)

    To save the plot as a png-file

    >>> utils.plot.plot_spectra(s).figure.savefig("test.png")

    Returns
    -------
    ax: matplotlib axes or list of matplotlib axes
        An array is returned when `style` is "mosaic".

    """
    import hyperspy.signal

    if style == "default":
        style = preferences.Plot.default_style_to_compare_spectra

    if color is not None:
        if hasattr(color, "__iter__"):
            color = itertools.cycle(color)
        elif isinstance(color, basestring):
            color = itertools.cycle([color])
        else:
            raise ValueError("Color must be None, a valid matplotlib color "
                             "string or a list of valid matplotlib colors.")
    else:
        color = itertools.cycle(plt.rcParams['axes.color_cycle'])

    if line_style is not None:
        if hasattr(line_style, "__iter__"):
            line_style = itertools.cycle(line_style)
        elif isinstance(line_style, basestring):
            line_style = itertools.cycle([line_style])
        else:
            raise ValueError("line_style must be None, a valid matplotlib"
                             " line_style string or a list of valid matplotlib"
                             " line_style.")
    else:
        line_style = ['-'] * len(spectra)

    if legend is not None:
        if legend == 'auto':
            legend = [spec.metadata.General.title for spec in spectra]
        elif hasattr(legend, "__iter__"):
            legend = itertools.cycle(legend)
        else:
            raise ValueError("legend must be None, 'auto' or a list of string")

    if style == 'overlap':
        if fig is None:
            fig = plt.figure()
        ax = fig.add_subplot(111)
        _make_overlap_plot(spectra,
                           ax,
                           color=color,
                           line_style=line_style,)
        if legend is not None:
            plt.legend(legend)
            if legend_picking is True:
                animate_legend(figure=fig)
    elif style == 'cascade':
        if fig is None:
            fig = plt.figure()
        ax = fig.add_subplot(111)
        _make_cascade_subplot(spectra,
                              ax,
                              color=color,
                              line_style=line_style,
                              padding=padding)
        if legend is not None:
            plt.legend(legend)
    elif style == 'mosaic':
        default_fsize = plt.rcParams["figure.figsize"]
        figsize = (default_fsize[0], default_fsize[1] * len(spectra))
        fig, subplots = plt.subplots(len(spectra), 1, figsize=figsize)
        if legend is None:
            legend = [legend] * len(spectra)
        for spectrum, ax, color, line_style, legend in zip(spectra,
                                                           subplots, color, line_style, legend):
            _plot_spectrum(spectrum, ax, color=color, line_style=line_style)
            ax.set_ylabel('Intensity')
            if legend is not None:
                ax.set_title(legend)
            if not isinstance(spectra, hyperspy.signal.Signal):
                _set_spectrum_xlabel(spectrum, ax)
        if isinstance(spectra, hyperspy.signal.Signal):
            _set_spectrum_xlabel(spectrum, ax)
        fig.tight_layout()

    elif style == 'heatmap':
        if not isinstance(spectra, hyperspy.signal.Signal):
            import hyperspy.utils
            spectra = hyperspy.utils.stack(spectra)
        refold = unfold_if_multidim(spectra)
        ax = _make_heatmap_subplot(spectra)
        ax.set_ylabel('Spectra')
        if refold is True:
            spectra.fold()
    ax = ax if style != "mosaic" else subplots

    return ax