Edge fitting with H-S GOS

100 views
Skip to first unread message

Magnus Nord

unread,
Jan 29, 2013, 6:21:55 AM1/29/13
to hypersp...@googlegroups.com
Hey,

I've been trying to fit a Ti-edge using H-S GOS, however the energy onset of the Ti edge is shifted towards higher energy.

Changing the Ti_L3.onset_energy parameter, then running m.fit (or m.smart_fit) gives the error: https://gist.github.com/6ac3946e978201d8328d . With the free_energy_shift set to True this error does not happen, however this can give some weird fitting results sometimes.

Magnus


Francisco de la Peña

unread,
Jan 29, 2013, 6:40:34 AM1/29/13
to hypersp...@googlegroups.com
Once more I'll need the script and the data to be helpful so what follows are just general comments.

The onset_energy should not be changed, use energy_shift instead if you need to modify the position of the edge. You'll have to free it first because by default it is fixed.

Letting the position parameter of any component can produce the sort of problems that you mention. If you really need to let the position free is advisable to use bounded optimization by  setting the energy_shift.bmin and energy_shift.bmax parameters of the component and using the mpfit fitter:

m.fit("mpfit", bounded=True)

Best,

Francisco


2013/1/29 Magnus Nord <magn...@gmail.com>


Magnus


--
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/groups/opt_out.
 
 

Magnus Nord

unread,
Jan 29, 2013, 7:01:33 AM1/29/13
to hypersp...@googlegroups.com
Is it possible to change the energy_shift.value without setting the parameter free?

STO.msa: http://ubuntuone.com/1MencUoHZszgemn4JiRuuM

s = load("STO.msa")
s.add_elements(("O", "Ti"))
s.set_microscope_parameters(beam_energy=300, convergence_angle=24.6, collection_angle=13.6)
m = create_model(s)
Ti_L3.energy_shift.value = 5.5
m.smart_fit()

Gives the error: https://gist.github.com/77fd5f73eeff7b9ab6e0

I'd rather not have it free I think, and just set it manually for each edge.

Magnus

Francisco de la Peña

unread,
Jan 29, 2013, 7:20:21 AM1/29/13
to hypersp...@googlegroups.com
This is a bug, thank you for reporting it. It only appears when using teh HartreeSlater cross sections. I won't have time to work on it in the next few days but you can use the hydrogenic cross sections for the time being:

m = create_model(s, GOS='hydrogenic')

Best wishes,

Magnus Nord

unread,
Jan 30, 2013, 12:54:46 PM1/30/13
to hypersp...@googlegroups.com
Is there some way to shift the spectrum, to workaround this bug?

Magnus

Francisco de la Peña

unread,
Jan 31, 2013, 5:56:47 AM1/31/13
to hypersp...@googlegroups.com
I think that my last commit fixes this bug, could you verify it?

Best,

Francisco

2013/1/30 Magnus Nord <magn...@gmail.com>

Magnus Nord

unread,
Jan 31, 2013, 6:51:51 AM1/31/13
to hypersp...@googlegroups.com
That seems to have fixed most of the problem, there is still an issue when doing the following:


s = load("STO.msa")
s.add_elements(("Ti",))
s.set_microscope_parameters(beam_energy=300, convergence_angle=24.6, collection_angle=18.6)
m = create_model(s)
m.plot() #Close the plot window
Ti_L3.energy_shift.value = 5.8
m.plot() #Or do a m.smart_fit()

Gives this error: https://gist.github.com/936dc6b9873c3266604b

Which only seems to happen when one uses m.plot(), closes it, change the energy_shift_value, and then do a plot or smart_fit. In addition it only seems to happen with the Ti_L3, not the Ti_L2.

In addition changing Ti_L2.energy_shift.value does not seem to do anything (changing Ti_L3.energy_shift.value works fine).

Magnus

Francisco de la Peña

unread,
Jan 31, 2013, 9:53:04 AM1/31/13
to hypersp...@googlegroups.com
I think that now it is fully fixed. Could you check it out?

Best,

Francisco

2013/1/31 Magnus Nord <magn...@gmail.com>

Magnus Nord

unread,
Jan 31, 2013, 10:01:23 AM1/31/13
to hypersp...@googlegroups.com
Yes, that fixed the problem. Thanks :)

Magnus

Magnus Nord

unread,
Jan 31, 2013, 12:27:21 PM1/31/13
to hypersp...@googlegroups.com
Another problem: when using H-S GOS the Ti_L2 and Ti_L3 are fairly close to eachother, so hyperspy limits the fine structure width of the L3, giving a gap between the L3 and L2 fine structure as shown in the image: http://ubuntuone.com/0f7Q4ONJZVJxWIr3yLYSMU

Magnus

Francisco de la Peña

unread,
Jan 31, 2013, 1:04:03 PM1/31/13
to hypersp...@googlegroups.com
Changing the values of "pre-onset region" and "Minimum distance between edges" to zero should give you a 0 gap between the FS. You can do it using the UI:

>>> preferences.gui()

An changes those parameters in the EELS -> Model tab or using the command line:

>>> preferences.EELS.min_distance_between_edges_for_fine_structure = 0
>>> preferences.EELS.preedge_safe_window_width = 0

The changes done using the UI are permanent. If you want to make the changes done using the command line permanent you have to call the save method:

>>> preferences.save()

That said, I think that out-of-the-box it should work as expected, so I'll try to improve the defaults.

Best wishes,

Magnus Nord

unread,
Feb 23, 2013, 2:25:50 PM2/23/13
to hypersp...@googlegroups.com
What is the copyright on the H-S GOS parameters from DM? I'm assuming we can't include it directly in Hyperspy.

 Is there some other source for the parameters, so we could include it directly?

Magnus

Francisco de la Peña

unread,
Feb 27, 2013, 4:11:01 AM2/27/13
to hypersp...@googlegroups.com
It seems that they are copyrighted although I didn't look too much into it. Some years ago I tried to find an alternative but I didn't find any. Probably it is a good idea to look again into this...

Francisco

2013/2/23 Magnus Nord <magn...@gmail.com>

Magnus Nord

unread,
Feb 27, 2013, 1:58:33 PM2/27/13
to hypersp...@googlegroups.com
I've been trying to do quantitative analysis of the fine structure of Ti by fitting 4 Voigt-functions (or Gaussian) to the Ti fine structure peaks.

I am using a powerlaw component to remove the background, and H-S GOS to fit the Ti-L3 and Ti-L2 edges. Then I extract the fine structure. I've been using two ways of doing this: Ti_L3.get_fine_structure_as_spectrum or by subtracting the model from the spectrum:

m() - m.spectrum()

Those should give approximately the same result (except for the fine structure smoothing)?

Doing the following:
fine_structure = np.append(Ti_L3.get_fine_structure_as_spectrum(), Ti_L2.get_fine_structure_as_spectrum())

Gives a fine structure spectrum with a discontinuity (attached image). Any ideas on how to solve this? I've been thinking about convolving the H-S GOS model with the experimental energy resolution to make the edges less "sharp".

Magnus

Ti_spectrum.png
Ti_fine_spectrum.png

Francisco de la Peña

unread,
Feb 28, 2013, 9:06:19 AM2/28/13
to hypersp...@googlegroups.com
Magnus,

2013/2/27 Magnus Nord <magn...@gmail.com>

I've been trying to do quantitative analysis of the fine structure of Ti by fitting 4 Voigt-functions (or Gaussian) to the Ti fine structure peaks.

I am using a powerlaw component to remove the background, and H-S GOS to fit the Ti-L3 and Ti-L2 edges. Then I extract the fine structure. I've been using two ways of doing this: Ti_L3.get_fine_structure_as_spectrum or by subtracting the model from the spectrum:

m() - m.spectrum()

Those should give approximately the same result (except for the fine structure smoothing)?

I  guess that this should return the residuals unless you have previously disabled the fine structure. If that is the case still you won't get get the same result because in Hyperspy the fine structure replaces the H-S calculations in the fine structure energy window and when you disable it the H-S values are returned in that window instead of the fitted fine structure.

 

Doing the following:
fine_structure = np.append(Ti_L3.get_fine_structure_as_spectrum(), Ti_L2.get_fine_structure_as_spectrum())

Gives a fine structure spectrum with a discontinuity (attached image). Any ideas on how to solve this?

I guess that you can solve this issue by disabling the Ti_L2 fine structure and increasing the Ti_L3.fine_structure_width to cover  the Ti L3,2 fine structure, e.g.

>>> Ti_L2.fine_structure_active = False
>>> Ti_L3.fine_structure_width += Ti_L2.fine_structure_width

 
I've been thinking about convolving the H-S GOS model with the experimental energy resolution to make the edges less "sharp".

In principle it should be enough to play with the fine_structure_smoothing attribute, but if you need to fine tune it then convolving it with e.g. a gaussian it's certainly the way to go. You can do it changing from Spectrum to SpectrumSimulation and using the apply_spectral_gaussian_filter method. By the way, maybe we should move this method to Spectrum so that we don't need to change to SpectrumSimulation to use it.

Best,

Francisco
 

Magnus Nord

unread,
Mar 3, 2013, 3:49:10 PM3/3/13
to hypersp...@googlegroups.com

I  guess that this should return the residuals unless you have previously disabled the fine structure. If that is the case still you won't get get the same result because in Hyperspy the fine structure replaces the H-S calculations in the fine structure energy window and when you disable it the H-S values are returned in that window instead of the fitted fine structure.
Yes, I meant with the fine structure disabled. And I'm a curious, how exactly does the fine structure fitting work? I thought it worked by fitting the H-S to the area which is not defined as the fine structure, then simply defining the fine structure as the residual after the H-S and background is subtracted from the spectrum.


In principle it should be enough to play with the fine_structure_smoothing attribute, but if you need to fine tune it then convolving it with e.g. a gaussian it's certainly the way to go. You can do it changing from Spectrum to SpectrumSimulation and using the apply_spectral_gaussian_filter method. By the way, maybe we should move this method to Spectrum so that we don't need to change to SpectrumSimulation to use it.

apply_spectral_gaussian_filter seems to work, but it seems to convolve the spectrum by using the array indexes rather then the signal axes. Meaning:

s = load("some_spectrum").to_simulation()
b = signals.spectrum_simulation.SpectrumSimulation({'data':s()})
s.apply_spectral_gaussian_filter(10)
b.apply_spectral_gaussian_filter(10)
s() - b() #Gives a zero array

Is there some way to make apply_spectral_gaussian_filter work on the signal axis unit scaling instead of the array index number. Basically meaning s.apply_spectral_gaussian_filter(10) would convolve the spectrum by a gaussian with a FWHM of 10 eV (if that is the signal axis unit).

Moving the function to Spectrum seems like a good idea.

Magnus
 

Francisco de la Peña

unread,
Mar 5, 2013, 4:57:22 AM3/5/13
to hypersp...@googlegroups.com

[...]And I'm a curious, how exactly does the fine structure fitting work?

Hyperspy fits a spline to the region marked as fine structure. More details about this procedure can be found in:

Manoubi, T., Tence, M., Walls, M. G. & Colliex, C. Curve fitting methods for quantitative analysis in electron energy loss spectroscopy. Microscopy Microanalysis Microstructures 1, 23 (1990).


apply_spectral_gaussian_filter seems to work, but it seems to convolve the spectrum by using the array indexes rather then the signal axes. Meaning:

s = load("some_spectrum").to_simulation()
b = signals.spectrum_simulation.SpectrumSimulation({'data':s()})
s.apply_spectral_gaussian_filter(10)
b.apply_spectral_gaussian_filter(10)
s() - b() #Gives a zero array

Is there some way to make apply_spectral_gaussian_filter work on the signal axis unit scaling instead of the array index number. Basically meaning s.apply_spectral_gaussian_filter(10) would convolve the spectrum by a gaussian with a FWHM of 10 eV (if that is the signal axis unit).

Moving the function to Spectrum seems like a good idea.

Yes, that was a bug, thank you for reporting it. I moved the function to the Spectrum class, renamed it to gaussian_filter and fixed this and another bug. Everything is up in the master branch.

Best,

Francisco


 

Magnus Nord

unread,
Mar 6, 2013, 10:08:33 AM3/6/13
to hypersp...@googlegroups.com


On Tuesday, March 5, 2013 10:57:22 AM UTC+1, francisco wrote:

[...]And I'm a curious, how exactly does the fine structure fitting work?

Hyperspy fits a spline to the region marked as fine structure. More details about this procedure can be found in:
What kind of function is used for the spline? In that article they use Lorentz distributions ontop of the H-S to fit the fine structure

Manoubi, T., Tence, M., Walls, M. G. & Colliex, C. Curve fitting methods for quantitative analysis in electron energy loss spectroscopy. Microscopy Microanalysis Microstructures 1, 23 (1990).


apply_spectral_gaussian_filter seems to work, but it seems to convolve the spectrum by using the array indexes rather then the signal axes. Meaning:

s = load("some_spectrum").to_simulation()
b = signals.spectrum_simulation.SpectrumSimulation({'data':s()})
s.apply_spectral_gaussian_filter(10)
b.apply_spectral_gaussian_filter(10)
s() - b() #Gives a zero array

Is there some way to make apply_spectral_gaussian_filter work on the signal axis unit scaling instead of the array index number. Basically meaning s.apply_spectral_gaussian_filter(10) would convolve the spectrum by a gaussian with a FWHM of 10 eV (if that is the signal axis unit).

Moving the function to Spectrum seems like a good idea.

Yes, that was a bug, thank you for reporting it. I moved the function to the Spectrum class, renamed it to gaussian_filter and fixed this and another bug. Everything is up in the master branch...

There was a small bug in this implementation, I fixed it with: https://github.com/hyperspy/hyperspy/commit/a1c4fb698269bd49eedc18b3a05b4dc58a5b50f3

Magnus
 

Francisco de la Peña

unread,
Mar 6, 2013, 10:50:16 AM3/6/13
to hypersp...@googlegroups.com
Magnus,

2013/3/6 Magnus Nord <magn...@gmail.com>



On Tuesday, March 5, 2013 10:57:22 AM UTC+1, francisco wrote:

[...]And I'm a curious, how exactly does the fine structure fitting work?

Hyperspy fits a spline to the region marked as fine structure. More details about this procedure can be found in:
What kind of function is used for the spline? In that article they use Lorentz distributions ontop of the H-S to fit the fine structure

Yes, in the article they use lorentzians to fit the whitelines and they point out that you can use any function that fits well the fine structure features. A spline fits well mostly anything that is well behaved and that is why it is the function that Hyperspy uses by default. Splines are good if you are only interested in elemental quantification but it is probably not optimal for quantifying the fine structure that I presume that it is what you're trying to do.

In your case I would do the following:

1. activate the fine structure of the Ti_L3 and Ti_L2 edges but fix them.By default this will set the fine structure region of the Ti L3,2 edges to zero.

>>> Ti_L3.fine_structure_active  =False
>>> Ti_L2.fine_structure_active  =False
>>> Ti_L3.fine_structure_coeff.free = False
>>> Ti_L2.fine_structure_coeff.free = False

2. Add components to the model to fit your whitelines and set the
starting parameters and possible the boundings to reasonable values.

I guess this should give you what you want. However, I must admit that it is a little bit cumbersome. To make the task easier I was thinking to add the possibilty to set a model as the fine structure of a given component. I'll show you with an example what I mean:

>>> s.add_elements(("Sr", "Ti", "O"))
>>> Ti_L32_FS = create_model(s)
>>> g1,  g2 = components.Gaussian(), components.Gaussian()
>>> Ti_L32_FS.extend((g1, g2))
>>> m = create_model(s)
>>> Ti_L3.fine_structure_mode = Ti_L32_FS

What do you think?
 

There was a small bug in this implementation, I fixed it with: https://github.com/hyperspy/hyperspy/commit/a1c4fb698269bd49eedc18b3a05b4dc58a5b50f3

Thanks!

Best,

Francisco
 

Magnus Nord

unread,
Mar 7, 2013, 6:20:38 AM3/7/13
to hypersp...@googlegroups.com


On Wednesday, March 6, 2013 4:50:16 PM UTC+1, francisco wrote:
Magnus,

2013/3/6 Magnus Nord <magn...@gmail.com>


On Tuesday, March 5, 2013 10:57:22 AM UTC+1, francisco wrote:

[...]And I'm a curious, how exactly does the fine structure fitting work?

Hyperspy fits a spline to the region marked as fine structure. More details about this procedure can be found in:
What kind of function is used for the spline? In that article they use Lorentz distributions ontop of the H-S to fit the fine structure

Yes, in the article they use lorentzians to fit the whitelines and they point out that you can use any function that fits well the fine structure features. A spline fits well mostly anything that is well behaved and that is why it is the function that Hyperspy uses by default. Splines are good if you are only interested in elemental quantification but it is probably not optimal for quantifying the fine structure that I presume that it is what you're trying to do.

In your case I would do the following:

1. activate the fine structure of the Ti_L3 and Ti_L2 edges but fix them.By default this will set the fine structure region of the Ti L3,2 edges to zero.

>>> Ti_L3.fine_structure_active  =False
>>> Ti_L2.fine_structure_active  =False
>>> Ti_L3.fine_structure_coeff.free = False
>>> Ti_L2.fine_structure_coeff.free = False

2. Add components to the model to fit your whitelines and set the
starting parameters and possible the boundings to reasonable values.

That works. In addition I need some way to apply a Gaussian convolution to some of the components (for example the H-S components), is there some way to convolve a component in a model? I'm guessing it should be fairly straight forward to implement: adding the gaussian_filter function from the spectrum class to the model class, and then add a check in the function which generates the model-array to see if the gaussian_filter function should be used to convolve the model-array.
 

I guess this should give you what you want. However, I must admit that it is a little bit cumbersome. To make the task easier I was thinking to add the possibilty to set a model as the fine structure of a given component. I'll show you with an example what I mean:

>>> s.add_elements(("Sr", "Ti", "O"))
>>> Ti_L32_FS = create_model(s)
>>> g1,  g2 = components.Gaussian(), components.Gaussian()
>>> Ti_L32_FS.extend((g1, g2))
>>> m = create_model(s)
>>> Ti_L3.fine_structure_mode = Ti_L32_FS

What do you think?
 
Yes, that would be nice. But I'm not certain how difficult it would be to implement something like this.

Magnus
 

Francisco de la Peña

unread,
Mar 7, 2013, 6:32:32 AM3/7/13
to hypersp...@googlegroups.com
Magnus,


I just noticed, and probably you've noticed it too, that there was a typo in the code of my previous post. Where I wrote:

>>> Ti_L3.fine_structure_active  =False
>>> Ti_L2.fine_structure_active  =False


I Should have writtend:

>>> Ti_L3.fine_structure_active  = True
>>> Ti_L2.fine_structure_active  = True


That works. In addition I need some way to apply a Gaussian convolution to some of the components (for example the H-S components), is there some way to convolve a component in a model? I'm guessing it should be fairly straight forward to implement: adding the gaussian_filter function from the spectrum class to the model class, and then add a check in the function which generates the model-array to see if the gaussian_filter function should be used to convolve the model-array.

When Model.low_loss is defined Hyperspy automatically convolves the spectrum with the spectrum stored in the low_loss attribute. If you are already using this feature then probably you don't need to convolve your spectrum with anything else. Otherwise you can create a spectrum object of the same dimensions as your experimental spectrum containing the functions that you want to convolve your model with and it should work. All the model components are convolved by default except those that are marked as background. You can control whether to convolve or not a given component by setting its convolved attribute.

Best,

Francisco
Reply all
Reply to author
Forward
0 new messages