Accessing relative strength of EELSModel components

231 views
Skip to first unread message

Josh Taillon

unread,
Mar 2, 2015, 7:50:01 PM3/2/15
to hypersp...@googlegroups.com
Hello,

I'm trying to model changes in valence in Mn using the ratio of L3/L2 intensity. I've managed to run the smart_fit routine (including L2 and L3 components) over my line scan signal, and now I was hoping to be able to divide the intensity of each component at each point in the line scan. The ultimate goal would be a new signal, equal in spatial dimension to the original scan, but with the ratio of the two components as the value in each place. 

Here is what I've run so far (multismartfit() is just a function that does the same thing as multifit(), using smart_fit() instead of fit()), but it seems as though the A parameter is the same at every point: 

```
sig = load("hyperspy_files/line3-mn/line3-high.hdf5")
sig.decomposition()
decomp_mod = sig.get_decomposition_model(components=4)
decomp_mod.add_elements(('Mn',))
sig_EELS_mod = create_model(decomp_mod)
sig_EELS_mod.multismartfit()

for index in sig_EELS_mod:
    sig_EELS_mod.fetch_stored_values()
    sig_EELS_mod['Mn_L2'].fetch_stored_values()
    sig_EELS_mod['Mn_L3'].fetch_stored_values()
    print Mn_L3.A / Mn_L2.A
```

Thanks,
Josh

Francisco de la Pena

unread,
Mar 4, 2015, 9:46:09 AM3/4/15
to hypersp...@googlegroups.com


> (multismartfit() is just a function that does the same thing as
> multifit(), using smart_fit() instead of fit()),

`multifit` can use `smart_fit`: `m.multifit(kind="smart")`

Once you run the fitter you could get the ratio like this:

ratio = Mn_L3.A.as_signal() / Mn_L2.A.as_signal()

I hope that this helps.

Francisco


> but it seems as though the A parameter is the same at every point:
>
>
> ```
> sig = load("hyperspy_files/line3-mn/line3-high.hdf5")
> sig.decomposition()
> decomp_mod = sig.get_decomposition_model(components=4)
> decomp_mod.add_elements(('Mn',))
> sig_EELS_mod = create_model(decomp_mod)
> sig_EELS_mod.multismartfit()
>
>
>
> for index in sig_EELS_mod:
> sig_EELS_mod.fetch_stored_values()
> sig_EELS_mod['Mn_L2'].fetch_stored_values()
> sig_EELS_mod['Mn_L3'].fetch_stored_values()
> print Mn_L3.A / Mn_L2.A
> ```
>
>
> Thanks,
> Josh
> --
> You received this message because you are subscribed to the Google
> Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to hyperspy-user...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.


Josh Taillon

unread,
Mar 4, 2015, 12:27:51 PM3/4/15
to hypersp...@googlegroups.com
Hi Francisco,

Thanks for the advice. I didn't realize you could specify the smart fit option in the regular fit method. I've added this method to the user guide, since I couldn't find any reference to it. You'll see a PR come through shortly.

Otherwise, it appears that I cannot call Mn_L3.A.as_signal(), since A is not a parameter, but merely a value. It appears the parameter that would be of interest is the Mn_L3.intensity one, but if I look at those, they appear identical (see attached images). 

It appears that this might be the total Mn intensity, and it's not broken out for each edge? I'm not sure, and I'll take a closer look at the code to see if I can't figure it out.

For reference, here's some output from the model describing the traits:

Thanks,
Josh


> For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "hyperspy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hyperspy-users+unsubscribe@googlegroups.com.
figure_intensity_parameter_of_mn_l2_component_signal.png
figure_intensity_parameter_of_mn_l3l2_ratio_component_signal.png
figure_intensity_parameter_of_mn_l3_component_signal.png

Francisco de la Pena

unread,
Mar 4, 2015, 1:02:22 PM3/4/15
to hypersp...@googlegroups.com
Sorry, I thought that Mn_L3 was a Gaussian component. The EELSCLEdge
component doesn't have an `A` attribute, does it?

In any case, you're right, the only things that should change from pixel
to pixel are the value of the parameters. To measure the ratio of the
area of the white lines you can add Gaussian components to the model to
approximately model the white lines. Would do be good enough for your
purposes?

Francisco.
> > an email to hyperspy-user...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the
> Google Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from
> it, send an email to hyperspy-users
> +unsub...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> --
> You received this message because you are subscribed to the Google
> Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to hyperspy-user...@googlegroups.com.

Josh Taillon

unread,
Mar 4, 2015, 1:09:12 PM3/4/15
to hypersp...@googlegroups.com
Yes, that seems to be the problem. 

Doing it with Gaussian components was actually my first thought, but I figured I would give it a try with the EELSCLEdge components, since that's what they're designed for anyway. I'll reply back once I've worked something out in case it is useful for others

>         > an email to hyperspy-users+unsubscribe@googlegroups.com.

>         > For more options, visit https://groups.google.com/d/optout.
>
>
>         --
>         You received this message because you are subscribed to the
>         Google Groups "hyperspy-users" group.
>         To unsubscribe from this group and stop receiving emails from
>         it, send an email to hyperspy-users
>         +unsub...@googlegroups.com.
>         For more options, visit https://groups.google.com/d/optout.
> --
> You received this message because you are subscribed to the Google
> Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from it, send

> For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "hyperspy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hyperspy-users+unsubscribe@googlegroups.com.

Francisco de la Pena

unread,
Mar 5, 2015, 9:11:13 AM3/5/15
to hypersp...@googlegroups.com
What about adding both to the model, the EELSCLEdge and the gaussian or
lorentzian peaks?
> > > an email to hyperspy-users
> +unsub...@googlegroups.com.
> > > For more options, visit
> https://groups.google.com/d/optout.
> >
> >
> > --
> > You received this message because you are subscribed
> to the
> > Google Groups "hyperspy-users" group.
> > To unsubscribe from this group and stop receiving
> emails from
> > it, send an email to hyperspy-users
> > +unsub...@googlegroups.com.
> > For more options, visit
> https://groups.google.com/d/optout.
> > --
> > You received this message because you are subscribed to the
> Google
> > Groups "hyperspy-users" group.
> > To unsubscribe from this group and stop receiving emails
> from it, send
> > an email to hyperspy-user...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the
> Google Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from
> it, send an email to hyperspy-users
> +unsub...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> --
> You received this message because you are subscribed to the Google
> Groups "hyperspy-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to hyperspy-user...@googlegroups.com.

Magnus Nord

unread,
Mar 5, 2015, 1:48:19 PM3/5/15
to hypersp...@googlegroups.com
I've been working quite extensively with fitting the fine structure of Manganese L23 peaks (and other transition metal L23-edges), for figuring out things like oxidation state. The quick-and-dirty approach is either fitting two gaussian to each L-peak, or simply summing up the electron counts within each peak-range.

Fitting the two EELSCLEdges including two gaussians require a little bit more work, since one needs to set the energy onset (which can move depending on oxidation state) of the EELSCLEdges in some robust fashion. I have code which does this fairly good, based on the method I described here: https://groups.google.com/d/msg/hyperspy-users/EkIPhtY7Nco/2JVzKivPaj4J but I haven't had time to integrate it into HyperSpy due to time constraints, although I plan to do this soonish, and probably even sooner if someone else needs this functionality.

Magnus

Magnus Nord

unread,
Mar 5, 2015, 1:52:46 PM3/5/15
to hypersp...@googlegroups.com
On Thursday, March 5, 2015 at 7:48:19 PM UTC+1, Magnus Nord wrote:
 The quick-and-dirty approach is either fitting two gaussian to each L-peak,

Correction: one gaussian for the L3 peak, and one gaussian for the L2 peak. Meaning a total of 2 gaussians. However if you have manganese with a oxidation state of +2.5 or similar, a gaussian will not fit very well.

Magnus
 

Joshua Taillon

unread,
Mar 11, 2015, 4:02:06 PM3/11/15
to hypersp...@googlegroups.com
Hi Magnus,

Thank you for your comments. Figuring out the valence of the Mn is exactly what I'm trying to do (mapping along a line or in a spectrum image). It appears that fitting a gaussian does not work very well (especially for the L2 peak):

Presumably this is because of the changing background? Attempting this with Voigt functions didn't work at all (although perhaps this is more due to my unfamiliarity with model fitting). 
Perhaps I will implement the counting method on a denoised data set. That should not be too difficult, unless you have another suggestion.

Thanks,
Josh

Joshua Taillon

unread,
Mar 11, 2015, 5:53:44 PM3/11/15
to hypersp...@googlegroups.com
I also wonder, when fitting with EELSCLEdge components, why the intensity parameters of the L2 and L3 components are identical. Is this a bug? I'm working through the code to try to figure this out, but I thought I might check with others to see if there are any thoughts.

- Josh

Magnus Nord

unread,
Mar 11, 2015, 5:56:26 PM3/11/15
to hypersp...@googlegroups.com
Hey Josh,

the most likely reason the Voigt functions are failing is the gamma parameter, which can lead to the Voigt function getting negative values at some places. I'm not certain if this is due to a bug in HyperSpy, or a property of the Voigt function itself. I mostly use Gaussians anyway, since I try to reduce the number of free parameters.

So I'm not certain why the L2 Gaussian is giving such a poor fit. From experience with my own datasets, it should fit much better. Is the range of the plotted model in your image the same as the signal range? If yes, I suspect that is the reason for the poor fit. Try to include less of the signal after the L2-peak, in your dataset the signal range can probably be set from 630 to ~656 eV.

Magnus

Magnus Nord

unread,
Mar 11, 2015, 6:07:57 PM3/11/15
to hypersp...@googlegroups.com
This is due to the Mn_L3 and Mn_L2 intensity parameters being connected through the twin variable, which means the L2 will always be L3 intensity times a constant (can't remember the exact number...). Similarly the Mn_L3 and Mn_L2 onset_energy parameters are connected, meaning the Mn_L3 and Mn_L2 edge onsets will be at a the same distance from eachother.

Using "Mn_L2.intensity.twin = None" should remove this connection, however I don't think that help you find the L23-ratio. Since the H-S edges does not fit the fine structure at all, just the "edge" itself.

Magnus

Josh Taillon

unread,
Mar 11, 2015, 6:40:26 PM3/11/15
to hypersp...@googlegroups.com
>>> Hi Magnus,

Thanks for the comments. The fit was performed over the range (630 - 670), originally. With a fit over the reduced range, the results look more like the attached image. 
This is closer, but clearly the gaussian components alone are not suitable to fit the data.

When you have been doing this kind of work, which technique do you use to measure the valence? I have had a look at the attached paper, and there are are a couple more complex techniques (such as the "Walsh-Dray" method) that will take some more work to implement. Perhaps this is a conversation that is more appropriate off-list, but I thought a record of the discussion might be useful to researchers attempting to use hyperspy for this kind of work.

- Josh








Josh Taillon

unread,
Mar 11, 2015, 7:01:00 PM3/11/15
to hypersp...@googlegroups.com
As a follow-up, I was able to get the Voigt components to work with some more tweaking. The following code allowed for a decent fit:

  m.set_parameters_value('centre', 641.5, component_list=[v1])
  m.set_parameters_value('centre', 652, component_list=[v2])
  m.set_parameters_value('FWHM', 0.5, component_list=[v1, v2])
  m.set_parameters_value('gamma', 0.5, component_list=[v1, v2])
  v1.centre.bmin = 640
  v1.centre.bmax = 645
  v1.centre.bounded = True
  v1.FWHM.bmin = 0.1
  v1.FWHM.bounded = True
  v1.gamma.bmin = 0.1
  v1.gamma.bounded = True

  v2.centre.bmin = 649
  v2.centre.bmax = 653
  v2.centre.bounded = True
  v2.FWHM.bmin = 0.1
  v2.FWHM.bounded = True
  v2.gamma.bmin = 0.1
  v2.gamma.bounded = True

  m.multifit(fitter='mpfit', bounded=True)

Gives the following:


I didn't realize that it was so important to explicitly set starting values for the parameters (especially when the signal is very weak in some areas), but once this is done, the fit seems to work as expected. I'm still missing a model for the continuum background though, which I feel I may have to build in myself.

Thanks,
Josh
--
Joshua Taillon
Materials Science and Engineering
University of Maryland, College Park

Magnus Nord

unread,
Mar 12, 2015, 6:23:22 AM3/12/15
to hypersp...@googlegroups.com
I made an Issue on GitHub about fitting the continuum background: https://github.com/hyperspy/hyperspy/issues/487 , I'll try to properly implement it into HyperSpy in a couple of weeks.

And setting bounds and initial values is very important for fitting the components. An easy way to set the initial values is using the model.fit_component function: https://github.com/hyperspy/hyperspy/blob/master/hyperspy/model.py#L1750

Magnus
Reply all
Reply to author
Forward
0 new messages