Пример #1
0
 def set_lines(self, lines, only_one=True, only_lines=('a', )):
     """Erase all Xrays lines and set them.
     See add_lines for details.
     Parameters
     ----------
     lines : list of strings
         A list of valid element X-ray lines to add e.g. Fe_Kb.
         Additionally, if `metadata.Sample.elements` is
         defined, add the lines of those elements that where not
         given in this list.
     only_one: bool
         If False, add all the lines of each element in
         `metadata.Sample.elements` that has not line
         defined in lines. If True (default),
         only add the line at the highest energy
         above an overvoltage of 2 (< beam energy / 2).
     only_lines : {None, list of strings}
         If not None, only the given lines will be added.
     Examples
     --------
     >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
     >>> s.add_lines()
     >>> print(s.metadata.Sample.xray_lines)
     >>> s.set_lines(['Cu_Ka'])
     >>> print(s.metadata.Sample.xray_lines)
     ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']
     ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Mn_La', 'Zr_La']
     See also
     --------
     add_lines, add_elements, set_elements
     """
     only_lines = utils_eds._parse_only_lines(only_lines)
     if "Sample.xray_lines" in self.metadata:
         del self.metadata.Sample.xray_lines
     self.add_lines(lines=lines, only_one=only_one, only_lines=only_lines)
Пример #2
0
    def _get_lines_from_elements(self,
                                 elements,
                                 only_one=False,
                                 only_lines=("a", )):
        """Returns the X-ray lines of the given elements in spectral range
        of the data.

        Parameters
        ----------
        elements : list of strings
            A list containing the symbol of the chemical elements.
        only_one : bool
            If False, add all the lines of each element in the data spectral
            range. If True only add the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, only the given lines will be returned.

        Returns
        -------
        list of X-ray lines alphabetically sorted

        """

        only_lines = utils_eds._parse_only_lines(only_lines)
        beam_energy = self._get_beam_energy()
        lines = []
        elements = [
            el if isinstance(el, str) else el.decode() for el in elements
        ]
        for element in elements:
            # Possible line (existing and excited by electron)
            element_lines = []
            for subshell in list(elements_db[element]['Atomic_properties']
                                 ['Xray_lines'].keys()):
                if only_lines and subshell not in only_lines:
                    continue
                element_lines.append(element + "_" + subshell)
            element_lines = self._get_xray_lines_in_spectral_range(
                element_lines)[0]
            if only_one and element_lines:
                # Choose the best line
                select_this = -1
                element_lines.sort()
                for i, line in enumerate(element_lines):
                    if (self._get_line_energy(line) < beam_energy / 2):
                        select_this = i
                        break
                element_lines = [
                    element_lines[select_this],
                ]

            if not element_lines:
                _logger.info(("There is no X-ray line for element %s " %
                              element) + "in the data spectral range")
            else:
                lines.extend(element_lines)
        lines.sort()
        return lines
Пример #3
0
    def _get_lines_from_elements(self,
                                 elements,
                                 only_one=False,
                                 only_lines=("a",)):
        """Returns the X-ray lines of the given elements in spectral range
        of the data.

        Parameters
        ----------
        elements : list of strings
            A list containing the symbol of the chemical elements.
        only_one : bool
            If False, add all the lines of each element in the data spectral
            range. If True only add the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, only the given lines will be returned.

        Returns
        -------
        list of X-ray lines alphabetically sorted

        """

        only_lines = utils_eds._parse_only_lines(only_lines)
        beam_energy = self._get_beam_energy()
        lines = []
        elements = [el if isinstance(el, str) else el.decode()
                    for el in elements]
        for element in elements:
            # Possible line (existing and excited by electron)
            element_lines = []
            for subshell in list(elements_db[element]['Atomic_properties'
                                                      ]['Xray_lines'].keys()):
                if only_lines and subshell not in only_lines:
                    continue
                element_lines.append(element + "_" + subshell)
            element_lines = self._get_xray_lines_in_spectral_range(
                element_lines)[0]
            if only_one and element_lines:
                # Choose the best line
                select_this = -1
                element_lines.sort()
                for i, line in enumerate(element_lines):
                    if (self._get_line_energy(line) < beam_energy / 2):
                        select_this = i
                        break
                element_lines = [element_lines[select_this], ]

            if not element_lines:
                _logger.info(
                    ("There is no X-ray line for element %s " % element) +
                    "in the data spectral range")
            else:
                lines.extend(element_lines)
        lines.sort()
        return lines
Пример #4
0
 def _parse_xray_lines(self, xray_lines, only_one, only_lines):
     only_lines = utils_eds._parse_only_lines(only_lines)
     xray_lines = self._get_xray_lines(xray_lines,
                                       only_one=only_one,
                                       only_lines=only_lines)
     xray_lines, xray_not_here = self._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 +
                       "You can remove it with" +
                       "s.metadata.Sample.xray_lines.remove('%s')" % xray)
     return xray_lines
Пример #5
0
 def _parse_xray_lines(self, xray_lines, only_one, only_lines):
     only_lines = utils_eds._parse_only_lines(only_lines)
     xray_lines = self._get_xray_lines(xray_lines,
                                       only_one=only_one,
                                       only_lines=only_lines)
     xray_lines, xray_not_here = self._get_xray_lines_in_spectral_range(
         xray_lines)
     for xray in xray_not_here:
         warnings.warn(f"{xray} is not in the data energy range. "
                       "You can remove it with: "
                       f"`s.metadata.Sample.xray_lines.remove('{xray}')`")
     return xray_lines
Пример #6
0
    def _plot_xray_lines(self,
                         xray_lines=False,
                         only_lines=("a", "b"),
                         only_one=False,
                         background_windows=None,
                         integration_windows=None,
                         render_figure=True):
        if (xray_lines is not False or background_windows is not None
                or integration_windows is not None):
            if xray_lines is False:
                xray_lines = True
            only_lines = utils_eds._parse_only_lines(only_lines)
            if xray_lines is True or xray_lines == 'from_elements':
                if ('Sample.xray_lines' in self.metadata
                        and xray_lines != 'from_elements'):
                    xray_lines = self.metadata.Sample.xray_lines
                elif 'Sample.elements' in self.metadata:
                    xray_lines = self._get_lines_from_elements(
                        self.metadata.Sample.elements,
                        only_one=only_one,
                        only_lines=only_lines)
                else:
                    _logger.warning(
                        "No elements defined, set them with `add_elements`")
                    # No X-rays lines, nothing to do then
                    return

            xray_lines, xray_not_here = self._get_xray_lines_in_spectral_range(
                xray_lines)
            for xray in xray_not_here:
                _logger.warning(f"{xray} is not in the data energy range.")
            xray_lines = np.unique(xray_lines)
            self.add_xray_lines_markers(xray_lines, render_figure=False)
            if background_windows is not None:
                self._add_background_windows_markers(background_windows,
                                                     render_figure=False)
            if integration_windows is not None:
                if integration_windows == 'auto':
                    integration_windows = 2.0
                if hasattr(integration_windows, '__iter__') is False:
                    integration_windows = self.estimate_integration_windows(
                        windows_width=integration_windows,
                        xray_lines=xray_lines)
                self._add_vertical_lines_groups(integration_windows,
                                                linestyle='--',
                                                render_figure=False)
        # Render figure only at the end
        if render_figure:
            self._render_figure(plot=['signal_plot'])
Пример #7
0
    def set_lines(self,
                  lines,
                  only_one=True,
                  only_lines=('a',)):
        """Erase all Xrays lines and set them.

        See add_lines for details.

        Parameters
        ----------
        lines : list of strings
            A list of valid element X-ray lines to add e.g. Fe_Kb.
            Additionally, if `metadata.Sample.elements` is
            defined, add the lines of those elements that where not
            given in this list.
        only_one: bool
            If False, add all the lines of each element in
            `metadata.Sample.elements` that has not line
            defined in lines. If True (default),
            only add the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, only the given lines will be added.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        >>> s.set_lines(['Cu_Ka'])
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']
        ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Mn_La', 'Zr_La']

        See also
        --------
        add_lines, add_elements, set_elements

        """
        only_lines = utils_eds._parse_only_lines(only_lines)
        if "Sample.xray_lines" in self.metadata:
            del self.metadata.Sample.xray_lines
        self.add_lines(lines=lines,
                       only_one=only_one,
                       only_lines=only_lines)
Пример #8
0
 def _plot_xray_lines(self,
                      xray_lines=False,
                      only_lines=("a", "b"),
                      only_one=False,
                      background_windows=None,
                      integration_windows=None):
     if xray_lines is not False or\
             background_windows is not None or\
             integration_windows is not None:
         if xray_lines is False:
             xray_lines = True
         only_lines = utils_eds._parse_only_lines(only_lines)
         if xray_lines is True or xray_lines == 'from_elements':
             if 'Sample.xray_lines' in self.metadata \
                     and xray_lines != 'from_elements':
                 xray_lines = self.metadata.Sample.xray_lines
             elif 'Sample.elements' in self.metadata:
                 xray_lines = self._get_lines_from_elements(
                     self.metadata.Sample.elements,
                     only_one=only_one,
                     only_lines=only_lines)
             else:
                 raise ValueError(
                     "No elements defined, set them with `add_elements`")
         xray_lines, xray_not_here = self._get_xray_lines_in_spectral_range(
             xray_lines)
         for xray in xray_not_here:
             _logger.warn("%s is not in the data energy range." % xray)
         xray_lines = np.unique(xray_lines)
         self.add_xray_lines_markers(xray_lines)
         if background_windows is not None:
             self._add_background_windows_markers(background_windows)
         if integration_windows is not None:
             if integration_windows == 'auto':
                 integration_windows = 2.0
             if hasattr(integration_windows, '__iter__') is False:
                 integration_windows = self.estimate_integration_windows(
                     windows_width=integration_windows,
                     xray_lines=xray_lines)
             self._add_vertical_lines_groups(integration_windows,
                                             linestyle='--')
Пример #9
0
 def _plot_xray_lines(self, xray_lines=False, only_lines=("a", "b"),
                      only_one=False, background_windows=None,
                      integration_windows=None):
     if xray_lines is not False or\
             background_windows is not None or\
             integration_windows is not None:
         if xray_lines is False:
             xray_lines = True
         only_lines = utils_eds._parse_only_lines(only_lines)
         if xray_lines is True or xray_lines == 'from_elements':
             if 'Sample.xray_lines' in self.metadata \
                     and xray_lines != 'from_elements':
                 xray_lines = self.metadata.Sample.xray_lines
             elif 'Sample.elements' in self.metadata:
                 xray_lines = self._get_lines_from_elements(
                     self.metadata.Sample.elements,
                     only_one=only_one,
                     only_lines=only_lines)
             else:
                 _logger.warning(
                     "No elements defined, set them with `add_elements`")
                 # No X-rays lines, nothing to do then
                 return
         xray_lines, xray_not_here = self._get_xray_lines_in_spectral_range(
             xray_lines)
         for xray in xray_not_here:
             _logger.warning("%s is not in the data energy range." % xray)
         xray_lines = np.unique(xray_lines)
         self.add_xray_lines_markers(xray_lines)
         if background_windows is not None:
             self._add_background_windows_markers(background_windows)
         if integration_windows is not None:
             if integration_windows == 'auto':
                 integration_windows = 2.0
             if hasattr(integration_windows, '__iter__') is False:
                 integration_windows = self.estimate_integration_windows(
                     windows_width=integration_windows,
                     xray_lines=xray_lines)
             self._add_vertical_lines_groups(integration_windows,
                                             linestyle='--')
Пример #10
0
    def get_lines_intensity(self,
                            xray_lines=None,
                            integration_windows=2.,
                            background_windows=None,
                            plot_result=False,
                            only_one=True,
                            only_lines=("a",),
                            **kwargs):
        """Return the intensity map of selected Xray lines.

        The intensities, the number of X-ray counts, are computed by
        suming the spectrum over the
        different X-ray lines. The sum window width
        is calculated from the energy resolution of the detector
        as defined in 'energy_resolution_MnKa' of the metadata.
        Backgrounds average in provided windows can be subtracted from the
        intensities.

        Parameters
        ----------
        xray_lines: {None, "best", list of string}
            If None,
            if `metadata.Sample.elements.xray_lines` contains a
            list of lines use those.
            If `metadata.Sample.elements.xray_lines` is undefined
            or empty but `metadata.Sample.elements` is defined,
            use the same syntax as `add_line` to select a subset of lines
            for the operation.
            Alternatively, provide an iterable containing
            a list of valid X-ray lines symbols.
        integration_windows: Float or array
            If float, the width of the integration windows is the
            'integration_windows_width' times the calculated FWHM of the line.
            Else provide an array for which each row corresponds to a X-ray
            line. Each row contains the left and right value of the window.
        background_windows: None or 2D array of float
            If None, no background subtraction. Else, the backgrounds average
            in the windows are subtracted from the return intensities.
            'background_windows' provides the position of the windows in
            energy. Each line corresponds to a X-ray line. In a line, the two
            first values correspond to the limits of the left window and the
            two last values correspond to the limits of the right window.
        plot_result : bool
            If True, plot the calculated line intensities. If the current
            object is a single spectrum it prints the result instead.
        only_one : bool
            If False, use all the lines of each element in the data spectral
            range. If True use only the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, use only the given lines.
        kwargs
            The extra keyword arguments for plotting. See
            `utils.plot.plot_signals`

        Returns
        -------
        intensities : list
            A list containing the intensities as Signal subclasses.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.get_lines_intensity(['Mn_Ka'], plot_result=True)
        Mn_La at 0.63316 keV : Intensity = 96700.00

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.plot(['Mn_Ka'], integration_windows=2.1)
        >>> s.get_lines_intensity(['Mn_Ka'],
        >>>                       integration_windows=2.1, plot_result=True)
        Mn_Ka at 5.8987 keV : Intensity = 53597.00

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.set_elements(['Mn'])
        >>> s.set_lines(['Mn_Ka'])
        >>> bw = s.estimate_background_windows()
        >>> s.plot(background_windows=bw)
        >>> s.get_lines_intensity(background_windows=bw, plot_result=True)
        Mn_Ka at 5.8987 keV : Intensity = 46716.00

        See also
        --------
        set_elements, add_elements, estimate_background_windows,
        plot

        """

        only_lines = utils_eds._parse_only_lines(only_lines)
        xray_lines = self._get_xray_lines(xray_lines, only_one=only_one,
                                          only_lines=only_lines)
        xray_lines, xray_not_here = self._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 +
                          "You can remove it with" +
                          "s.metadata.Sample.xray_lines.remove('%s')"
                          % xray)
        if hasattr(integration_windows, '__iter__') is False:
            integration_windows = self.estimate_integration_windows(
                windows_width=integration_windows, xray_lines=xray_lines)
        intensities = []
        ax = self.axes_manager.signal_axes[0]
        # test 1D Spectrum (0D problem)
        # signal_to_index = self.axes_manager.navigation_dimension - 2
        for i, (Xray_line, window) in enumerate(
                zip(xray_lines, integration_windows)):
            line_energy, line_FWHM = self._get_line_energy(Xray_line,
                                                           FWHM_MnKa='auto')
            element, line = utils_eds._get_element_and_line(Xray_line)
            img = self.isig[window[0]:window[1]].integrate1D(-1)
            if background_windows is not None:
                bw = background_windows[i]
                # TODO: test to prevent slicing bug. To be reomved when fixed
                indexes = [float(ax.value2index(de))
                           for de in list(bw) + window]
                if indexes[0] == indexes[1]:
                    bck1 = self.isig[bw[0]]
                else:
                    bck1 = self.isig[bw[0]:bw[1]].integrate1D(-1)
                if indexes[2] == indexes[3]:
                    bck2 = self.isig[bw[2]]
                else:
                    bck2 = self.isig[bw[2]:bw[3]].integrate1D(-1)
                corr_factor = (indexes[5] - indexes[4]) / (
                    (indexes[1] - indexes[0]) + (indexes[3] - indexes[2]))
                img -= (bck1 + bck2) * corr_factor
            img.metadata.General.title = (
                'X-ray line intensity of %s: %s at %.2f %s' %
                (self.metadata.General.title,
                 Xray_line,
                 line_energy,
                 self.axes_manager.signal_axes[0].units,
                 ))
            if img.axes_manager.navigation_dimension >= 2:
                img = img.as_image([0, 1])
            elif img.axes_manager.navigation_dimension == 1:
                img.axes_manager.set_signal_dimension(1)
            if plot_result and img.axes_manager.signal_dimension == 0:
                print("%s at %s %s : Intensity = %.2f"
                      % (Xray_line,
                         line_energy,
                         ax.units,
                         img.data))
            img.metadata.set_item("Sample.elements", ([element]))
            img.metadata.set_item("Sample.xray_lines", ([Xray_line]))
            intensities.append(img)
        if plot_result and img.axes_manager.signal_dimension != 0:
            utils.plot.plot_signals(intensities, **kwargs)
        return intensities
Пример #11
0
    def add_lines(self,
                  lines=(),
                  only_one=True,
                  only_lines=("a",)):
        """Add X-rays lines to the internal list.

        Although most functions do not require an internal list of
        X-ray lines because they can be calculated from the internal
        list of elements, ocassionally it might be useful to customize the
        X-ray lines to be use by all functions by default using this method.
        The list of X-ray lines is stored in
        `metadata.Sample.xray_lines`

        Parameters
        ----------
        lines : list of strings
            A list of valid element X-ray lines to add e.g. Fe_Kb.
            Additionally, if `metadata.Sample.elements` is
            defined, add the lines of those elements that where not
            given in this list. If the list is empty (default), and
            `metadata.Sample.elements` is
            defined, add the lines of all those elements.
        only_one: bool
            If False, add all the lines of each element in
            `metadata.Sample.elements` that has not line
            defined in lines. If True (default),
            only add the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, only the given lines will be added.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.set_microscope_parameters(beam_energy=30)
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Mn_Ka', 'Zr_La']

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        >>> s.add_lines(['Cu_Ka'])
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']
        ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Cu_La', 'Mn_La', 'Zr_La']

        See also
        --------
        set_lines, add_elements, set_elements

        """
        only_lines = utils_eds._parse_only_lines(only_lines)
        if "Sample.xray_lines" in self.metadata:
            xray_lines = set(self.metadata.Sample.xray_lines)
        else:
            xray_lines = set()
        # Define the elements which Xray lines has been customized
        # So that we don't attempt to add new lines automatically
        elements = set()
        for line in xray_lines:
            elements.add(line.split("_")[0])
        for line in lines:
            try:
                element, subshell = line.split("_")
            except ValueError:
                raise ValueError(
                    "Invalid line symbol. "
                    "Please provide a valid line symbol e.g. Fe_Ka")
            if element in elements_db:
                elements.add(element)
                if subshell in elements_db[element]['Atomic_properties'
                                                    ]['Xray_lines']:
                    lines_len = len(xray_lines)
                    xray_lines.add(line)
                    if lines_len != len(xray_lines):
                        _logger.info("%s line added," % line)
                    else:
                        _logger.info("%s line already in." % line)
                else:
                    raise ValueError(
                        "%s is not a valid line of %s." % (line, element))
            else:
                raise ValueError(
                    "%s is not a valid symbol of an element." % element)
        xray_not_here = self._get_xray_lines_in_spectral_range(xray_lines)[1]
        for xray in xray_not_here:
            warnings.warn("%s is not in the data energy range." % xray)
        if "Sample.elements" in self.metadata:
            extra_elements = (set(self.metadata.Sample.elements) -
                              elements)
            if extra_elements:
                new_lines = self._get_lines_from_elements(
                    extra_elements,
                    only_one=only_one,
                    only_lines=only_lines)
                if new_lines:
                    self.add_lines(list(new_lines) + list(lines))
        self.add_elements(elements)
        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')
        if "Sample.xray_lines" in self.metadata:
            xray_lines = xray_lines.union(
                self.metadata.Sample.xray_lines)
        self.metadata.Sample.xray_lines = sorted(list(xray_lines))
Пример #12
0
    def get_lines_intensity(self,
                            xray_lines=None,
                            integration_windows=2.,
                            background_windows=None,
                            plot_result=False,
                            only_one=True,
                            only_lines=("a", ),
                            **kwargs):
        """Return the intensity map of selected Xray lines.

        The intensities, the number of X-ray counts, are computed by
        suming the spectrum over the
        different X-ray lines. The sum window width
        is calculated from the energy resolution of the detector
        as defined in 'energy_resolution_MnKa' of the metadata.
        Backgrounds average in provided windows can be subtracted from the
        intensities.

        Parameters
        ----------
        xray_lines: {None, "best", list of string}
            If None,
            if `metadata.Sample.elements.xray_lines` contains a
            list of lines use those.
            If `metadata.Sample.elements.xray_lines` is undefined
            or empty but `metadata.Sample.elements` is defined,
            use the same syntax as `add_line` to select a subset of lines
            for the operation.
            Alternatively, provide an iterable containing
            a list of valid X-ray lines symbols.
        integration_windows: Float or array
            If float, the width of the integration windows is the
            'integration_windows_width' times the calculated FWHM of the line.
            Else provide an array for which each row corresponds to a X-ray
            line. Each row contains the left and right value of the window.
        background_windows: None or 2D array of float
            If None, no background subtraction. Else, the backgrounds average
            in the windows are subtracted from the return intensities.
            'background_windows' provides the position of the windows in
            energy. Each line corresponds to a X-ray line. In a line, the two
            first values correspond to the limits of the left window and the
            two last values correspond to the limits of the right window.
        plot_result : bool
            If True, plot the calculated line intensities. If the current
            object is a single spectrum it prints the result instead.
        only_one : bool
            If False, use all the lines of each element in the data spectral
            range. If True use only the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, use only the given lines.
        kwargs
            The extra keyword arguments for plotting. See
            `utils.plot.plot_signals`

        Returns
        -------
        intensities : list
            A list containing the intensities as BaseSignal subclasses.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.get_lines_intensity(['Mn_Ka'], plot_result=True)
        Mn_La at 0.63316 keV : Intensity = 96700.00

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.plot(['Mn_Ka'], integration_windows=2.1)
        >>> s.get_lines_intensity(['Mn_Ka'],
        >>>                       integration_windows=2.1, plot_result=True)
        Mn_Ka at 5.8987 keV : Intensity = 53597.00

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.set_elements(['Mn'])
        >>> s.set_lines(['Mn_Ka'])
        >>> bw = s.estimate_background_windows()
        >>> s.plot(background_windows=bw)
        >>> s.get_lines_intensity(background_windows=bw, plot_result=True)
        Mn_Ka at 5.8987 keV : Intensity = 46716.00

        See also
        --------
        set_elements, add_elements, estimate_background_windows,
        plot

        """

        only_lines = utils_eds._parse_only_lines(only_lines)
        xray_lines = self._get_xray_lines(xray_lines,
                                          only_one=only_one,
                                          only_lines=only_lines)
        xray_lines, xray_not_here = self._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 +
                          "You can remove it with" +
                          "s.metadata.Sample.xray_lines.remove('%s')" % xray)
        if hasattr(integration_windows, '__iter__') is False:
            integration_windows = self.estimate_integration_windows(
                windows_width=integration_windows, xray_lines=xray_lines)
        intensities = []
        ax = self.axes_manager.signal_axes[0]
        # test Signal1D (0D problem)
        # signal_to_index = self.axes_manager.navigation_dimension - 2
        for i, (Xray_line,
                window) in enumerate(zip(xray_lines, integration_windows)):
            line_energy, line_FWHM = self._get_line_energy(Xray_line,
                                                           FWHM_MnKa='auto')
            element, line = utils_eds._get_element_and_line(Xray_line)
            img = self.isig[window[0]:window[1]].integrate1D(-1)
            if np.issubdtype(img.data.dtype, np.integer):
                # The operations below require a float dtype with the default
                # numpy casting rule ('same_kind')
                img.change_dtype("float")
            if background_windows is not None:
                bw = background_windows[i]
                # TODO: test to prevent slicing bug. To be reomved when fixed
                indexes = [
                    float(ax.value2index(de)) for de in list(bw) + window
                ]
                if indexes[0] == indexes[1]:
                    bck1 = self.isig[bw[0]]
                else:
                    bck1 = self.isig[bw[0]:bw[1]].integrate1D(-1)
                if indexes[2] == indexes[3]:
                    bck2 = self.isig[bw[2]]
                else:
                    bck2 = self.isig[bw[2]:bw[3]].integrate1D(-1)
                corr_factor = (indexes[5] - indexes[4]) / (
                    (indexes[1] - indexes[0]) + (indexes[3] - indexes[2]))
                img = img - (bck1 + bck2) * corr_factor
            img.metadata.General.title = (
                'X-ray line intensity of %s: %s at %.2f %s' % (
                    self.metadata.General.title,
                    Xray_line,
                    line_energy,
                    self.axes_manager.signal_axes[0].units,
                ))
            img.axes_manager.set_signal_dimension(0)
            if plot_result and img.axes_manager.navigation_size == 1:
                print("%s at %s %s : Intensity = %.2f" %
                      (Xray_line, line_energy, ax.units, img.data))
            img.metadata.set_item("Sample.elements", ([element]))
            img.metadata.set_item("Sample.xray_lines", ([Xray_line]))
            intensities.append(img)
        if plot_result and img.axes_manager.navigation_size != 1:
            utils.plot.plot_signals(intensities, **kwargs)
        return intensities
Пример #13
0
    def add_lines(self, lines=(), only_one=True, only_lines=("a", )):
        """Add X-rays lines to the internal list.

        Although most functions do not require an internal list of
        X-ray lines because they can be calculated from the internal
        list of elements, ocassionally it might be useful to customize the
        X-ray lines to be use by all functions by default using this method.
        The list of X-ray lines is stored in
        `metadata.Sample.xray_lines`

        Parameters
        ----------
        lines : list of strings
            A list of valid element X-ray lines to add e.g. Fe_Kb.
            Additionally, if `metadata.Sample.elements` is
            defined, add the lines of those elements that where not
            given in this list. If the list is empty (default), and
            `metadata.Sample.elements` is
            defined, add the lines of all those elements.
        only_one: bool
            If False, add all the lines of each element in
            `metadata.Sample.elements` that has not line
            defined in lines. If True (default),
            only add the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        only_lines : {None, list of strings}
            If not None, only the given lines will be added.

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.set_microscope_parameters(beam_energy=30)
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Mn_Ka', 'Zr_La']

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.add_lines()
        >>> print(s.metadata.Sample.xray_lines)
        >>> s.add_lines(['Cu_Ka'])
        >>> print(s.metadata.Sample.xray_lines)
        ['Al_Ka', 'C_Ka', 'Cu_La', 'Mn_La', 'Zr_La']
        ['Al_Ka', 'C_Ka', 'Cu_Ka', 'Cu_La', 'Mn_La', 'Zr_La']

        See also
        --------
        set_lines, add_elements, set_elements

        """
        only_lines = utils_eds._parse_only_lines(only_lines)
        if "Sample.xray_lines" in self.metadata:
            xray_lines = set(self.metadata.Sample.xray_lines)
        else:
            xray_lines = set()
        # Define the elements which Xray lines has been customized
        # So that we don't attempt to add new lines automatically
        elements = set()
        for line in xray_lines:
            elements.add(line.split("_")[0])
        for line in lines:
            try:
                element, subshell = line.split("_")
            except ValueError:
                raise ValueError(
                    "Invalid line symbol. "
                    "Please provide a valid line symbol e.g. Fe_Ka")
            if element in elements_db:
                elements.add(element)
                if subshell in elements_db[element]['Atomic_properties'][
                        'Xray_lines']:
                    lines_len = len(xray_lines)
                    xray_lines.add(line)
                    if lines_len != len(xray_lines):
                        _logger.info("%s line added," % line)
                    else:
                        _logger.info("%s line already in." % line)
                else:
                    raise ValueError("%s is not a valid line of %s." %
                                     (line, element))
            else:
                raise ValueError("%s is not a valid symbol of an element." %
                                 element)
        xray_not_here = self._get_xray_lines_in_spectral_range(xray_lines)[1]
        for xray in xray_not_here:
            warnings.warn("%s is not in the data energy range." % xray)
        if "Sample.elements" in self.metadata:
            extra_elements = (set(self.metadata.Sample.elements) - elements)
            if extra_elements:
                new_lines = self._get_lines_from_elements(
                    extra_elements, only_one=only_one, only_lines=only_lines)
                if new_lines:
                    self.add_lines(list(new_lines) + list(lines))
        self.add_elements(elements)
        if not hasattr(self.metadata, 'Sample'):
            self.metadata.add_node('Sample')
        if "Sample.xray_lines" in self.metadata:
            xray_lines = xray_lines.union(self.metadata.Sample.xray_lines)
        self.metadata.Sample.xray_lines = sorted(list(xray_lines))
Пример #14
0
    def plot(self,
             xray_lines=False,
             only_lines=("a", "b"),
             only_one=False,
             background_windows=None,
             integration_windows=None,
             **kwargs):
        """
        Plot the EDS spectrum. The following markers can be added

        - The position of the X-ray lines and their names.
        - The background windows associated with each X-ray lines. A black line
        links the left and right window with the average value in each window.

        Parameters
        ----------
        xray_lines: {False, True, 'from_elements', list of string}
            If not False, indicate the position and the name of the X-ray
            lines.
            If True, if `metadata.Sample.elements.xray_lines` contains a
            list of lines use those. If `metadata.Sample.elements.xray_lines`
            is undefined or empty or if xray_lines equals 'from_elements' and
            `metadata.Sample.elements` is defined, use the same syntax as
            `add_line` to select a subset of lines for the operation.
            Alternatively, provide an iterable containing a list of valid X-ray
            lines symbols.
        only_lines : None or list of strings
            If not None, use only the given lines (eg. ('a','Kb')).
            If None, use all lines.
        only_one : bool
            If False, use all the lines of each element in the data spectral
            range. If True use only the line at the highest energy
            above an overvoltage of 2 (< beam energy / 2).
        background_windows: None or 2D array of float
            If not None, add markers at the position of the windows in energy.
            Each line corresponds to a X-ray lines. In a line, the two first
            value corresponds to the limit of the left window and the two
            last values corresponds to the limit of the right window.
        integration_windows: None or 'auto' or float or 2D array of float
            If not None, add markers at the position of the integration
            windows.
            If 'auto' (or float), the width of the integration windows is 2.0
            (or float) times the calculated FWHM of the line. see
            'estimate_integration_windows'.
            Else provide an array for which each row corresponds to a X-ray
            line. Each row contains the left and right value of the window.
        kwargs
            The extra keyword arguments for plot()

        Examples
        --------
        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.plot()

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.plot(True)

        >>> s = hs.datasets.example_signals.EDS_TEM_Spectrum()
        >>> s.add_lines()
        >>> bw = s.estimate_background_windows()
        >>> s.plot(background_windows=bw)

        >>> s = hs.datasets.example_signals.EDS_SEM_Spectrum()
        >>> s.plot(['Mn_Ka'], integration_windows='auto')

        >>> s = hs.datasets.example_signals.EDS_TEM_Spectrum()
        >>> s.add_lines()
        >>> bw = s.estimate_background_windows()
        >>> s.plot(background_windows=bw, integration_windows=2.1)

        See also
        --------
        set_elements, add_elements, estimate_integration_windows,
        get_lines_intensity, estimate_background_windows
        """
        super(EDSSpectrum, self).plot(**kwargs)
        if xray_lines is not False or\
                background_windows is not None or\
                integration_windows is not None:
            if xray_lines is False:
                xray_lines = True
            only_lines = utils_eds._parse_only_lines(only_lines)
            if xray_lines is True or xray_lines == 'from_elements':
                if 'Sample.xray_lines' in self.metadata \
                        and xray_lines != 'from_elements':
                    xray_lines = self.metadata.Sample.xray_lines
                elif 'Sample.elements' in self.metadata:
                    xray_lines = self._get_lines_from_elements(
                        self.metadata.Sample.elements,
                        only_one=only_one,
                        only_lines=only_lines)
                else:
                    raise ValueError(
                        "No elements defined, set them with `add_elements`")
            xray_lines, xray_not_here = self._get_xray_lines_in_spectral_range(
                xray_lines)
            for xray in xray_not_here:
                print("Warning: %s is not in the data energy range." % xray)
            xray_lines = np.unique(xray_lines)
            self._add_xray_lines_markers(xray_lines)
            if background_windows is not None:
                self._add_background_windows_markers(background_windows)
            if integration_windows is not None:
                if integration_windows == 'auto':
                    integration_windows = 2.0
                if hasattr(integration_windows, '__iter__') is False:
                    integration_windows = self.estimate_integration_windows(
                        windows_width=integration_windows,
                        xray_lines=xray_lines)
                self._add_vertical_lines_groups(integration_windows,
                                                linestyle='--')