def setup_method(self, method): gaussian = components1d.Gaussian() gaussian.A.value = 10 gaussian.centre.value = 10 gaussian.sigma.value = 1 self.signal = signals.Signal1D( gaussian.function(np.arange(0, 20, 0.01))) self.signal.axes_manager[0].scale = 0.01
def setUp(self): gaussian = components1d.Gaussian() gaussian.A.value = 10 gaussian.centre.value = 10 gaussian.sigma.value = 1 self.signal = signals.Signal1D( gaussian.function(np.arange(0, 20, 0.01))) self.signal.axes_manager[0].scale = 0.01 self.signal.metadata.Signal.binned = False
def get_low_loss_eels_signal(add_noise=True, random_state=None): """Get an artificial low loss electron energy loss spectrum. The zero loss peak is offset by 4.1 eV. Parameters ---------- %s %s Example ------- >>> s = hs.datasets.artificial_data.get_low_loss_eels_signal() >>> s.plot() See also -------- get_core_loss_eels_signal, get_core_loss_eels_model, get_low_loss_eels_line_scan_signal, get_core_loss_eels_line_scan_signal """ random_state = check_random_state(random_state) x = np.arange(-100, 400, 0.5) zero_loss = components1d.Gaussian(A=100, centre=4.1, sigma=1) plasmon = components1d.Gaussian(A=100, centre=60, sigma=20) data = zero_loss.function(x) data += plasmon.function(x) if add_noise: data += random_state.uniform(size=len(x)) * 0.7 s = signals.EELSSpectrum(data) s.axes_manager[0].offset = x[0] s.axes_manager[0].scale = x[1] - x[0] s.metadata.General.title = 'Artifical low loss EEL spectrum' s.axes_manager[0].name = 'Electron energy loss' s.axes_manager[0].units = 'eV' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s
def get_low_loss_eels_line_scan_signal(): """Get an artificial low loss electron energy loss line scan spectrum. The zero loss peak is offset by 4.1 eV. Returns ------- artificial_low_loss_line_scan_signal : HyperSpy EELSSpectrum Example ------- >>> s = hs.datasets.artificial_data.get_low_loss_eels_signal() >>> s.plot() See also -------- get_core_loss_eels_signal : get a core loss signal get_core_loss_eels_model : get a core loss model get_core_loss_eels_line_scan_signal : core loss signal with the same size """ x = np.arange(-100, 400, 0.5) zero_loss = components1d.Gaussian(A=100, centre=4.1, sigma=1) plasmon = components1d.Gaussian(A=100, centre=60, sigma=20) data_signal = zero_loss.function(x) data_signal += plasmon.function(x) data = np.zeros((12, len(x))) for i in range(12): data[i] += data_signal data[i] += np.random.random(size=len(x)) * 0.7 s = EELSSpectrum(data) s.axes_manager.signal_axes[0].offset = x[0] s.axes_manager.signal_axes[0].scale = x[1] - x[0] s.metadata.General.title = 'Artifical low loss EEL spectrum' s.axes_manager.signal_axes[0].name = 'Electron energy loss' s.axes_manager.signal_axes[0].units = 'eV' s.axes_manager.navigation_axes[0].name = 'Probe position' s.axes_manager.navigation_axes[0].units = 'nm' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s
def get_low_loss_eels_signal(): """Get an artificial low loss electron energy loss spectrum. The zero loss peak is offset by 4.1 eV. Returns ------- artificial_low_loss_signal : HyperSpy EELSSpectrum Example ------- >>> s = hs.datasets.artificial_data.get_low_loss_eels_signal() >>> s.plot() See also -------- get_core_loss_eels_signal : get a core loss signal get_core_loss_eels_model : get a core loss model get_low_loss_eels_line_scan_signal : get EELS low loss line scan get_core_loss_eels_line_scan_signal : get EELS core loss line scan """ from hyperspy.signals import EELSSpectrum from hyperspy import components1d x = np.arange(-100, 400, 0.5) zero_loss = components1d.Gaussian(A=100, centre=4.1, sigma=1) plasmon = components1d.Gaussian(A=100, centre=60, sigma=20) data = zero_loss.function(x) data += plasmon.function(x) data += np.random.random(size=len(x)) * 0.7 s = EELSSpectrum(data) s.axes_manager[0].offset = x[0] s.axes_manager[0].scale = x[1] - x[0] s.metadata.General.title = 'Artifical low loss EEL spectrum' s.axes_manager[0].name = 'Electron energy loss' s.axes_manager[0].units = 'eV' s.set_microscope_parameters( beam_energy=200, convergence_angle=26, collection_angle=20) return s
def get_core_loss_eels_signal(): """Get an artificial core loss electron energy loss spectrum. Similar to a Mn-L32 edge from a perovskite oxide. Returns ------- artificial_core_loss_signal : HyperSpy EELSSpectrum Example ------- >>> s = hs.datasets.artificial_data.get_core_loss_eels_signal() >>> s.plot() See also -------- get_low_loss_eels_model : get a low loss signal get_core_loss_eels_model : get a model instead of a signal get_low_loss_eels_line_scan_signal : get EELS low loss line scan get_core_loss_eels_line_scan_signal : get EELS core loss line scan """ x = np.arange(400, 800, 1) arctan = components1d.Arctan(A=1, k=0.2, x0=688) arctan.minimum_at_zero = True mn_l3_g = components1d.Gaussian(A=100, centre=695, sigma=4) mn_l2_g = components1d.Gaussian(A=20, centre=720, sigma=4) data = arctan.function(x) data += mn_l3_g.function(x) data += mn_l2_g.function(x) data += np.random.random(size=len(x)) * 0.7 s = EELSSpectrum(data) s.axes_manager[0].offset = x[0] s.metadata.General.title = 'Artifical core loss EEL spectrum' s.axes_manager[0].name = 'Electron energy loss' s.axes_manager[0].units = 'eV' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s
def set_background_estimator(self): if self.background_type == 'Power Law': self.background_estimator = components1d.PowerLaw() self.bg_line_range = 'from_left_range' elif self.background_type == 'Gaussian': self.background_estimator = components1d.Gaussian() self.bg_line_range = 'full' elif self.background_type == 'Offset': self.background_estimator = components1d.Offset() self.bg_line_range = 'full' elif self.background_type == 'Polynomial': self.background_estimator = components1d.Polynomial( self.polynomial_order) self.bg_line_range = 'full'
def xray_lines_model(elements, beam_energy=200, weight_percents=None, energy_resolution_MnKa=130, energy_axis=None): """ Generate a model of X-ray lines using a Gaussian distribution for each peak. The area under a main peak (alpha) is equal to 1 and weighted by the composition. Parameters ---------- elements : list of strings A list of chemical element symbols. beam_energy: float The energy of the beam in keV. weight_percents: list of float The composition in weight percent. energy_resolution_MnKa: float The energy resolution of the detector in eV energy_axis: dic The dictionary for the energy axis. It must contains 'size' and the units must be 'eV' of 'keV'. Example ------- >>> s = xray_lines_model(['Cu', 'Fe'], beam_energy=30) >>> s.plot() """ from hyperspy._signals.eds_tem import EDSTEMSpectrum from hyperspy import components1d if energy_axis is None: energy_axis = { 'name': 'E', 'scale': 0.01, 'units': 'keV', 'offset': -0.1, 'size': 1024 } s = EDSTEMSpectrum(np.zeros(energy_axis['size']), axes=[energy_axis]) s.set_microscope_parameters(beam_energy=beam_energy, energy_resolution_MnKa=energy_resolution_MnKa) s.add_elements(elements) counts_rate = 1. live_time = 1. if weight_percents is None: weight_percents = [100. / len(elements)] * len(elements) m = s.create_model() if len(elements) == len(weight_percents): for (element, weight_percent) in zip(elements, weight_percents): for line, properties in elements_db[element]['Atomic_properties'][ 'Xray_lines'].items(): line_energy = properties['energy (keV)'] ratio_line = properties['weight'] if s._get_xray_lines_in_spectral_range([element + '_' + line ])[1] == []: g = components1d.Gaussian() g.centre.value = line_energy g.sigma.value = get_FWHM_at_Energy( energy_resolution_MnKa, line_energy) / sigma2fwhm g.A.value = live_time * counts_rate * \ weight_percent / 100 * ratio_line m.append(g) else: raise ValueError("The number of elements specified is not the same " "as the number of weight_percents") s.data = m.as_signal().data return s
def add_family_lines(self, xray_lines='from_elements'): """Create the Xray-lines instances and configure them appropiately If a X-ray line is given, all the the lines of the familiy is added. For instance if Zn Ka is given, Zn Kb is added too. The main lines (alpha) is added to self.xray_lines Parameters ----------- xray_lines: {None, 'from_elements', list of string} If None, if `metadata` contains `xray_lines` list of lines use those. If 'from_elements', add all lines from the elements contains in `metadata`. Alternatively, provide an iterable containing a list of valid X-ray lines symbols. (eg. ('Al_Ka','Zn_Ka')). """ only_one = False only_lines = ("Ka", "La", "Ma") if xray_lines is None or xray_lines == 'from_elements': if 'Sample.xray_lines' in self.signal.metadata \ and xray_lines != 'from_elements': xray_lines = self.signal.metadata.Sample.xray_lines elif 'Sample.elements' in self.signal.metadata: xray_lines = self.signal._get_lines_from_elements( self.signal.metadata.Sample.elements, only_one=only_one, only_lines=only_lines) else: raise ValueError( "No elements defined, set them with `add_elements`") components_names = [xr.name for xr in self.xray_lines] xray_lines = filter(lambda x: x not in components_names, xray_lines) xray_lines, xray_not_here = self.signal.\ _get_xray_lines_in_spectral_range(xray_lines) for xray in xray_not_here: warnings.warn("%s is not in the data energy range." % (xray)) for xray_line in xray_lines: element, line = utils_eds._get_element_and_line(xray_line) line_energy, line_FWHM = self.signal._get_line_energy( xray_line, FWHM_MnKa='auto') component = create_component.Gaussian() component.centre.value = line_energy component.fwhm = line_FWHM component.centre.free = False component.sigma.free = False component.name = xray_line self.append(component) self.xray_lines.append(component) self[xray_line].A.map[ 'values'] = self.signal.isig[line_energy].data * \ line_FWHM / self.signal.axes_manager[-1].scale self[xray_line].A.map['is_set'] = (np.ones( self.signal.isig[line_energy].data.shape) == 1) component.A.ext_force_positive = True for li in elements_db[element]['Atomic_properties']['Xray_lines']: if line[0] in li and line != li: xray_sub = element + '_' + li if self.signal.\ _get_xray_lines_in_spectral_range( [xray_sub])[0] != []: line_energy, line_FWHM = self.signal.\ _get_line_energy( xray_sub, FWHM_MnKa='auto') component_sub = create_component.Gaussian() component_sub.centre.value = line_energy component_sub.fwhm = line_FWHM component_sub.centre.free = False component_sub.sigma.free = False component_sub.name = xray_sub component_sub.A.twin_function = _get_weight( element, li) component_sub.A.twin_inverse_function = _get_iweight( element, li) component_sub.A.twin = component.A self.append(component_sub) self.fetch_stored_values()
def remove_background(self, signal_range='interactive', background_type='PowerLaw', polynomial_order=2, fast=True, show_progressbar=None): """Remove the background, either in place using a gui or returned as a new spectrum using the command line. Parameters ---------- signal_range : tuple, optional If this argument is not specified, the signal range has to be selected using a GUI. And the original spectrum will be replaced. If tuple is given, the a spectrum will be returned. background_type : string The type of component which should be used to fit the background. Possible components: PowerLaw, Gaussian, Offset, Polynomial If Polynomial is used, the polynomial order can be specified polynomial_order : int, default 2 Specify the polynomial order if a Polynomial background is used. fast : bool If True, perform an approximative estimation of the parameters. If False, the signal is fitted using non-linear least squares afterwards.This is slower compared to the estimation but possibly more accurate. show_progressbar : None or bool If True, display a progress bar. If None the default is set in `preferences`. Examples -------- Using gui, replaces spectrum s >>>> s.remove_background() Using command line, returns a spectrum >>>> s = s.remove_background(signal_range=(400,450), background_type='PowerLaw') Using a full model to fit the background >>>> s = s.remove_background(signal_range=(400,450), fast=False) Raises ------ SignalDimensionError if the signal dimension is not 1. """ self._check_signal_dimension_equals_one() if signal_range == 'interactive': br = BackgroundRemoval(self) br.edit_traits() else: if background_type == 'PowerLaw': background_estimator = components1d.PowerLaw() elif background_type == 'Gaussian': background_estimator = components1d.Gaussian() elif background_type == 'Offset': background_estimator = components1d.Offset() elif background_type == 'Polynomial': background_estimator = components1d.Polynomial( polynomial_order) else: raise ValueError("Background type: " + background_type + " not recognized") spectra = self._remove_background_cli( signal_range=signal_range, background_estimator=background_estimator, fast=fast, show_progressbar=show_progressbar) return spectra
def get_core_loss_eels_signal(add_powerlaw=False, add_noise=True, random_state=None): """Get an artificial core loss electron energy loss spectrum. Similar to a Mn-L32 edge from a perovskite oxide. Some random noise is also added to the spectrum, to simulate experimental noise. Parameters ---------- %s %s %s Example ------- >>> import hs.datasets.artifical_data as ad >>> s = ad.get_core_loss_eels_signal() >>> s.plot() With the powerlaw background >>> s = ad.get_core_loss_eels_signal(add_powerlaw=True) >>> s.plot() To make the noise the same for multiple spectra, which can be useful for testing fitting routines >>> s1 = ad.get_core_loss_eels_signal(random_state=10) >>> s2 = ad.get_core_loss_eels_signal(random_state=10) >>> (s1.data == s2.data).all() True See also -------- get_core_loss_eels_line_scan_signal, get_low_loss_eels_line_scan_signal, get_core_loss_eels_model """ from hyperspy.signals import EELSSpectrum from hyperspy import components1d random_state = check_random_state(random_state) x = np.arange(400, 800, 1) arctan = components1d.EELSArctan(A=1, k=0.2, x0=688) mn_l3_g = components1d.Gaussian(A=100, centre=695, sigma=4) mn_l2_g = components1d.Gaussian(A=20, centre=720, sigma=4) data = arctan.function(x) data += mn_l3_g.function(x) data += mn_l2_g.function(x) if add_noise: data += random_state.uniform(size=len(x)) * 0.7 if add_powerlaw: powerlaw = components1d.PowerLaw(A=10e8, r=3, origin=0) data += powerlaw.function(x) s = EELSSpectrum(data) s.axes_manager[0].offset = x[0] s.metadata.General.title = 'Artifical core loss EEL spectrum' s.axes_manager[0].name = 'Electron energy loss' s.axes_manager[0].units = 'eV' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s
def get_core_loss_eels_line_scan_signal(add_powerlaw=False, add_noise=True, random_state=None): """Get an artificial core loss electron energy loss line scan spectrum. Similar to a Mn-L32 and Fe-L32 edge from a perovskite oxide. Parameters ---------- %s %s %s Example ------- >>> s = hs.datasets.artificial_data.get_core_loss_eels_line_scan_signal() >>> s.plot() See also -------- get_low_loss_eels_line_scan_signal, get_core_loss_eels_model """ from hyperspy.signals import EELSSpectrum from hyperspy import components1d random_state = check_random_state(random_state) x = np.arange(400, 800, 1) arctan_mn = components1d.EELSArctan(A=1, k=0.2, x0=688) arctan_fe = components1d.EELSArctan(A=1, k=0.2, x0=612) mn_l3_g = components1d.Gaussian(A=100, centre=695, sigma=4) mn_l2_g = components1d.Gaussian(A=20, centre=720, sigma=4) fe_l3_g = components1d.Gaussian(A=100, centre=605, sigma=4) fe_l2_g = components1d.Gaussian(A=10, centre=630, sigma=3) mn_intensity = [1, 1, 1, 1, 1, 1, 0.8, 0.5, 0.2, 0, 0, 0] fe_intensity = [0, 0, 0, 0, 0, 0, 0.2, 0.5, 0.8, 1, 1, 1] data = np.zeros((len(mn_intensity), len(x))) for i in range(len(mn_intensity)): data[i] += arctan_mn.function(x) * mn_intensity[i] data[i] += mn_l3_g.function(x) * mn_intensity[i] data[i] += mn_l2_g.function(x) * mn_intensity[i] data[i] += arctan_fe.function(x) * fe_intensity[i] data[i] += fe_l3_g.function(x) * fe_intensity[i] data[i] += fe_l2_g.function(x) * fe_intensity[i] if add_noise: data[i] += random_state.uniform(size=len(x)) * 0.7 if add_powerlaw: powerlaw = components1d.PowerLaw(A=10e8, r=3, origin=0) data += powerlaw.function_nd(np.stack([x] * len(mn_intensity))) if add_powerlaw: powerlaw = components1d.PowerLaw(A=10e8, r=3, origin=0) data += powerlaw.function(x) s = EELSSpectrum(data) s.axes_manager.signal_axes[0].offset = x[0] s.metadata.General.title = 'Artifical core loss EEL spectrum' s.axes_manager.signal_axes[0].name = 'Electron energy loss' s.axes_manager.signal_axes[0].units = 'eV' s.axes_manager.navigation_axes[0].name = 'Probe position' s.axes_manager.navigation_axes[0].units = 'nm' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s
def get_luminescence_signal(navigation_dimension=0, uniform=False, add_baseline=False, add_noise=True, random_state=None): """Get an artificial luminescence signal in wavelength scale (nm, uniform) or energy scale (eV, non-uniform), simulating luminescence data recorded with a diffracting spectrometer. Some random noise is also added to the spectrum, to simulate experimental noise. Parameters ---------- navigation_dimension: positive int. The navigation dimension(s) of the signal. 0 = single spectrum, 1 = linescan, 2 = spectral map etc... uniform: bool. return uniform (wavelength) or non-uniform (energy) spectrum add_baseline : bool If true, adds a constant baseline to the spectrum. Conversion to energy representation will turn the constant baseline into inverse powerlaw. %s Example ------- >>> import hyperspy.datasets.artificial_data as ad >>> s = ad.get_luminescence_signal() >>> s.plot() With constant baseline >>> s = ad.get_luminescence_signal(uniform=True, add_baseline=True) >>> s.plot() To make the noise the same for multiple spectra, which can be useful for testing fitting routines >>> s1 = ad.get_luminescence_signal(random_state=10) >>> s2 = ad.get_luminescence_signal(random_state=10) >>> (s1.data == s2.data).all() True 2D map >>> s = ad.get_luminescence_signal(navigation_dimension=2) >>> s.plot() See also -------- get_low_loss_eels_signal, get_core_loss_eels_signal, get_low_loss_eels_line_scan_signal, get_core_loss_eels_line_scan_signal, get_core_loss_eels_model, get_atomic_resolution_tem_signal2d, """ #Initialisation of random number generator random_state = check_random_state(random_state) #Creating a uniform data axis, roughly similar to Horiba iHR320 with a 150 mm-1 grating nm_axis = UniformDataAxis( index_in_array=None, name="Wavelength", units="nm", navigate=False, size=1024, scale=0.54, offset=222.495, is_binned=False, ) #Artificial luminescence peak gaussian_peak = components1d.Gaussian(A=5000, centre=375, sigma=25) if navigation_dimension >= 0: #Generate empty data (ones) data = np.ones([10 for i in range(navigation_dimension)] + [nm_axis.size]) #Generate spatial axes spaxes = [ UniformDataAxis( index_in_array=None, name="X{:d}".format(i), units="um", navigate=False, size=10, scale=2.1, offset=0, is_binned=False, ) for i in range(navigation_dimension) ] #Generate empty signal sig = signals.Signal1D(data, axes=spaxes + [nm_axis]) sig.metadata.General.title = '{:d}d-map Artificial Luminescence Signal'\ .format(navigation_dimension) else: raise ValueError("Value {:d} invalid as navigation dimension.".format(\ navigation_dimension)) #Populating data array, possibly with noise and baseline sig.data *= gaussian_peak.function(nm_axis.axis) if add_noise: sig.data += (random_state.uniform(size=sig.data.shape) - 0.5) * 1.4 if add_baseline: data += 350. #if not uniform, transformation into non-uniform axis if not uniform: hc = 1239.84198 #nm/eV #converting to non-uniform axis sig.axes_manager.signal_axes[0].convert_to_functional_data_axis(\ expression="a/x", name='Energy', units='eV', a=hc, ) #Reverting the orientation of signal axis to have increasing Energy sig = sig.isig[::-1] #Jacobian transformation Eax = sig.axes_manager.signal_axes[0].axis sig *= hc / Eax**2 return sig
def get_core_loss_eels_signal(add_powerlaw=False): """Get an artificial core loss electron energy loss spectrum. Similar to a Mn-L32 edge from a perovskite oxide. Some random noise is also added to the spectrum, to simulate experimental noise. Parameters ---------- add_powerlaw : bool If True, adds a powerlaw background to the spectrum. Default False. Returns ------- artificial_core_loss_signal : HyperSpy EELSSpectrum Example ------- >>> import hs.datasets.artifical_data as ad >>> s = ad.get_core_loss_eels_signal() >>> s.plot() With the powerlaw background >>> s = ad.get_core_loss_eels_signal(add_powerlaw=True) >>> s.plot() To make the noise the same for multiple spectra, which can be useful for testing fitting routines >>> np.random.seed(seed=10) >>> s1 = ad.get_core_loss_eels_signal() >>> np.random.seed(seed=10) >>> s2 = ad.get_core_loss_eels_signal() >>> (s1.data == s2.data).all() True See also -------- get_low_loss_eels_model : get a low loss signal get_core_loss_eels_model : get a model instead of a signal get_low_loss_eels_line_scan_signal : get EELS low loss line scan get_core_loss_eels_line_scan_signal : get EELS core loss line scan """ x = np.arange(400, 800, 1) arctan = components1d.Arctan(A=1, k=0.2, x0=688) arctan.minimum_at_zero = True mn_l3_g = components1d.Gaussian(A=100, centre=695, sigma=4) mn_l2_g = components1d.Gaussian(A=20, centre=720, sigma=4) data = arctan.function(x) data += mn_l3_g.function(x) data += mn_l2_g.function(x) data += np.random.random(size=len(x)) * 0.7 if add_powerlaw: powerlaw = components1d.PowerLaw(A=10e8, r=3, origin=0) data += powerlaw.function(x) s = EELSSpectrum(data) s.axes_manager[0].offset = x[0] s.metadata.General.title = 'Artifical core loss EEL spectrum' s.axes_manager[0].name = 'Electron energy loss' s.axes_manager[0].units = 'eV' s.set_microscope_parameters(beam_energy=200, convergence_angle=26, collection_angle=20) return s