hyperspy / hyperspy

Multidimensional data analysis
https://hyperspy.org
GNU General Public License v3.0
501 stars 205 forks source link

Clarify intensity and quantify in EELS model #2562

Open ericpre opened 3 years ago

ericpre commented 3 years ago

from https://gitter.im/hyperspy/hyperspy?at=5f91eed3631a250ab286ce2f

Weixin Song @winston-song Oct 22 21:42

I have a pretty simple question regarding the EELS quantification. I had a good look at the documentation but could not find an answer. If it is there, then please send me the link.
The function: m.quantify() - “prints the intensity at the current locations of all the EELS ionisation edges in the model” according to the documentation. I have collected a STEM-EELS SI of 100x100 pixels and want to plot a quantitative map for a particular element. After all the standard pre-processing and model-fitting I run the command: m["Cr_L3"].intensity.as_signal() to get the intensity of this edge to create a 2D map. A. My first question is regarding the definition of “intensity”, does it refer to the absolute quantification (including the cross-sections etc) or is it just one of the fitting parameters of the edge corresponding to the peak height? The BN example in the documentation gives a value of 0.045648 for the single spectrum quantification, what are the units for this value? B. Is the m.quantify() function equivalent to m[“Edge”].intensity.as_signal()? C. If they are not the same, how do I extract a 2D quantification map for a particular element.

Thanks, Johan

I also have the same question for a long time, I currently think the intensity value from quantify() is a number devided by the cross section, and different from edge.intensity, I hope any expert in this function can give more precise answer

lukmuk @lukmuk 11:08 @jwestraadt @winston-song I was also wondering about the same thing, but from my results it also seems that it is scaled by the cross-sections. When I normalize the m.quantify() values by their sum (i.e. print the values in at%), I get similar results as for a quantification in DigitalMicrograph (which includes the cross-sections).

lukmuk commented 3 years ago

I can not speak for the other two commenters, but here are my thoughts on this issue: When doing EELS quantification with the "integration window" method (Egerton chapter 4.5.1), the power-law background is substracted before the core-loss edge and then the raw EELS signal intensity is integrated in an energy window after the edge. This raw signal intensity is then weighted by the partial (Hartree-Slater) scattering cross-section for quantification, e.g., when comparing the concentration ratio between two elements (Egerton, eq. (4.66)). Therefore, the "intensity" in this context is not yet scaled by the scattering cross-section, i.e. just the raw EELS signal intensity. For MLLS fitting as in HyperSpy the situation might be different as the scattering cross-section models (and a background model) are directly fitted onto the signal (as far as I understand it). I think it the confusion arises because of the differences in this definition of the "intensity" (what comes out by MLLS fitting) and "raw intensity" (in the context of the raw EELS signal as describe above).

ericpre commented 3 years ago

@lukmuk, you have got it right - except that, to be accurate, hyperspy fitting isn't MLLS (multiple linear least square) but it is non-linear fitting. In the context of EELSModel, intensity is a parameter of the EELS_cl_edge component. Calling the as_signal method of this parameter will return the parameter values as a hyperspy signal.

As described in the component docstring, the intensity is "the factor by which the cross section is multiplied", which means that this parameter value is proportional to the number of atoms of the corresponding chemical element. As such, this value doesn't have an units.

The quantify method simply prints the current values of active edges.

I think that using the word "absolute" (see for example below) when printing the results of the fit is a bit misleading:

>>> m.quantify()
Absolute quantification:
Elem.       Intensity
B   0.045648
N   0.048061

Other than that, it seems to me that the documentation is accurate but it would be good to elaborate more on this in the user guide. Does anyone of you would like to make a pull request to improve the user guide and clarify the physical meaning of the intensity parameter and the output of quantify?

jwestraadt commented 3 years ago

@ericpre, @lukmuk and @winston-song Thank you for your comments and clarifications. I managed to also find the docstring and even pocked around the source code to figure that the intensity is just a scaling parameter that incorporates the cross-section. Thus the ratio of this intensity value for two elements in the sample should be the same as atomic ratio, from my current understanding. My expectation of the m.quantify() function is that it should take whatever elements (edges) you supplied to the model, work out the "intensity value" and give a normalised/absolute elemental (at%) quantification. For example, the output of the BN example could be B = 50%; N = 50%,

lukmuk commented 3 years ago

@ericpre @jwestraadt Sorry for the late reply and thank you for your inputs. I agree with @ericpre that, the "Absolute quantification" was also confusing to me (albeit it may actually make sense in this context?). I have still not found time (yet!) to set up HyperSpy on my computer for an active envolvement (is on my todo list), but here are my suggestions:

For quantify() we should maybe add a link to the eels_cl_edge component so that users directly find information on the "intensity" value.

The proposed at%-quantification output of @jwestraadt mimics the function of EELS quantification in DigitalMicrograph (which will always normalize to the sum of all analyzed EELS edge intensities in the current spectrum). However, imho, this is only a useful output if all relevant elements in the sample have an EELS signal/edge in the analyzed spectrum. I would instead keep the current output of quantify() (or add an extra keyword for a "normalized-to-sum of all intensities at% output" as proposed above). Instead, what about an update to the user guide where an at%-quantification for the BN sample is shown? I.e., 0.045648/(0.045648+0.048061) = 0.49 at% for B 0.048061/(0.045648+0.048061) = 0.51 at% for N I think this would already remove the problems we had with understanding the output of quantify().

To help with the calculation of at% elemental ratios, the quantify() (or a new) function could also return the intensity values directly as values, which would be more convenient (imo) than m[edge].intensity (similar to get_lines_intensity() for EDS).

ericpre commented 3 years ago

@lukmuk, yes I completely agree with your suggestions!

To set up a development environment, the development installation instructions should work be fairly straightforward in a miniconda distribution (https://hyperspy.readthedocs.io/en/latest/user_guide/install.html#installation-in-a-anaconda-minconda-distribution):

# Create and activate new environment
conda create -n hspy-dev
conda activate hspy-dev
# Install dependencies
conda install hyperspy-base -c conda-forge --only-deps
conda install hyperspy-dev -c conda-forge
# From the hyperspy development folder, install in development mode
pip install -e . --no-deps
zezhong-zhang commented 3 years ago

Is it possible to have the absolute intensity (the intensity factor * H-S scs) or show the value of H-S cross-section under the given microscope condition? As I want to know their exact product to calculate the partial cross-section…

que-vector commented 2 years ago

Is it possible to have the absolute intensity (the intensity factor * H-S scs) or show the value of H-S cross-section under the given microscope condition? As I want to know their exact product to calculate the partial cross-section…

I am also interessted in this.