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
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
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
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