Multi peak Lorentzian curve fitting


I have some x-ray scattering data for some materials and I have 16 spectra for each material. In one spectra, there are around 8 or 9 peak positions.

The peak positions and the FWHM values should be the same for all 16 spectra. I did my preliminary data fitting using the multipeak package. But it took some time to fit all the spectra one by one.

So I am planning to use global fitting and prior to that, I was trying to fit one spectrum using the normal curve fitting option. I used a user-defined equation with multi peaks as follows:

f(x) = y0 + A1/(4*(x-x1)^2 + w1^2)+ A2/(4*(x-x2)^2 + w2^2)+ A3/(4*(x-x3)^2 + w3^2)+ A4/(4*(x-x4)^2 + w4^2)+ A5/(4*(x-x5)^2 + w5^2)+ A6/(4*(x-x6)^2 + w6^2)+ A7/(4*(x-x7)^2 + w7^2)+ A8/(4*(x-x8)^2 + w8^2)

But it doesn't give me a good fitting. Can you please trouble shoot this.


Thank you,

When you say, "In one spectra, there are around 8 or 9 peak positions." that seems to imply that the number of peaks varies from one fit to the next. If that is the case, you will have to hold all the coefficients for peaks that aren't present to prevent the extra peaks from participating in the fit, or causing a singular matrix error.

Maybe a better solution would be to use Igor 9, where there is a nice GUI for Multipeak batch fitting (thank you, chozo!).


For a given material, the number of peaks doesn't change. And I am using igor 9. Can we hold the parameters in multi peak batch fitting?

First, the question is if you want to keep the FWHM and position the same for all spectra while doing the fit (i.e., the fit should find the optimal global FWHM and position for all data sets) or if it is OK to predefine the position and FWHM and just let the fit find the other parameters in each set separately. In the former case, I am afraid that you have to keep going with global fit, since Multipeak Fit is unable to fit multiple spectra simultaneously. In the latter case, this is not very difficult. Have you already tried out the batch-fitting user interface (Analysis -> Multipeak Fitting -> Automatic Multipeak Batch Fitting)? You can read the details how this works in the provided help (or ask questions here).

Now, constraining the positions or FWHM to a fixed value in Multipeak (batch) fitting is possible by preparing a constraints wave. This is a text wave which contains entries with logical expressions like K4 < 10. To fix a parameter to a certain number you cannot use the equal sign. Instead you have two entries which constrains the parameter from both sides, e.g., K4 < 10 and K4 > 10 (this example fixes parameter 4 to 10). Now what is this K4 about? It represents the fifth parameter in your overall fit (counting starts from K0). To find out which parameter you want to work with you just have to count your baseline parameters and your peaks, starting from the first. For example, if you have a constant baseline with two gaussians then the fifth parameter will be the position of the second gaussian (since the order is 'baseline height; Gauss1Loc; Gauss1W; Gauss1H; Gauss2Loc; Gauss2W; Gauss2H;').

If you tell us a bit more about your particular problem or are even willing to provide some test data, then we can help you with more specific answers.

Thank you. This helps a lot. 

Here is my detailed procedure for data fitting.

For one data set first I need to find the peak positions. The number of peaks should be between 8 to 12. I have to repeat this for all 16 spectra.

Then by plotting a histogram or by another method, I need to determine the most precious peak positions and keep the peak positions constant for all 16 spectra. Then I have to do the fitting again.

As the next step, again I need to determine the most precious FWHM values somehow.

Finally, I need to keep the peak positions and the FWHM values constant and do the fitting again. In the final step, the only variables are amplitude and the area.

I have done all this data fitting manually by using the multi-peak package. I am trying to automate this as much as possible.


OK, I see. Thanks for your explanation. I am not sure about the physical meaning behind successively constraining parameters in the fit, but all these steps can be very much automated. This will involve a bit of writing scripts to prepare each successive step.

First, I unfortunately have to tell you that I had overlooked a bug in the release version of Multipeak Fit, which prevents the use of constraints with the Auto Multipeak Batch Fit user interface. If you want use it the way I describe below then please first write the support (John in this case) an email and ask for the latest version. There are of course ways to do it without the user interface, but this involves more scripting.

To get started, have all the (16?) data sets you want to fit loaded into the AutoMPFit user interface so that they appear in the list to the left. Then you (theoretically) need to do these steps:

1) Set Initial Guess Options to 5: Auto guess and fit. When you press Do Fit the peak finder will run and finds a number of peaks in all your data sets and do the fit. You will find new result folders (one for each data set) with a number of peak coefficient waves. You may now want to think of some way to decide whether the right number of peaks at the right places have been found. If not then you could tweak the Optional Settings until you have the desired output for all data sets.

Our you decide to provide initial guesses yourself and prepare the peak coefficient waves with the right values (then some things need to change here, but I assume the standard fit will do just fine for now). Additionally you may want to check 'I want Derived Values' to get additional output of things like area values etc.

2) Now its scripting time: Find the 'most precious' peak positions and write them down in a constraints (text) wave in the right format (entries with Kxx < pos and Kxx > pos each) to keep them fixed. You probably need to search and compare the position parameter of each peak coefficient wave in each data set folder. I guess this involves two nested for-loops to go through everything. If you have your constraints wave prepared, go back to the user interface and select this constraints wave under Optional Settings while leaveing everything else as before. You may actually want to set the Initial Guess option to 2, since you already have very good initial parameters for your data inside the folders. Then do the fit again.

3) Do the same as in step 2), but now with your FWHMs. The constraints go into the same constraints wave, but now for the FWHM parameters. Since you can only have one constraints wave, both the position and FWHM constraints need to go in there together. Then do the fit again.

4) Extract all desired parameters such as areas from each peak in each set folder (preferably with another small script).

This should give you the results you want in a fairly automated way. The most 'difficult' part may be automating the setup of step 2 and 3, i.e., deciding and preparing the constraints. But this should be only a small script if you have well-defined criteria for finding good positions and FHWMs. If you want a fire-and-forget approach at some point you can also easily go over to a UI-less approach by programming the in-between steps in one big script. After all, the user interface also just ends up calling a function for fitting.

Please let me know if you need further help. If you have trouble getting everything set up the right way (especially constraints) there are ways to first try it the manual way using the Multipeak Fit user interface.

Thanks a lot. This is exactly what I wanted. I will try this out soon. I really appreciate your help. 

I have in the past tackled the problem you describe. In my case, the waves to be fit were polarised infrared spectra from the same sample, but with different polarisation directions. This means that the position, width and shape (I was fitting Voigt lineforms) should be the same in each spectrum, but amplitudes may vary.

Global fit is designed to handle this.

However, for this kind of fitting (and multipeak fitting in general) it is absolutely crucial to have good initial guesses. small adjustments in initial guesses for fit coefficients can have a large effect on the fit. Because of this, I ended up writing my own code, which is essentially a wrapper for FuncFit that is hardwired to the peak function and the constrained coefficient set. My code implements a user interface for setting up the initial guesses using mouse movements, scroll wheel and modifier keys to fine-tune the peak parameters.

I attach the code here. It got the job done for me, but your mileage may vary - it's not very 'polished' and could be buggy - I haven't looked at this in years. Maybe this gives you some ideas.


I will add that perhaps Global Fit is the right way to do this job. If you have good initial guesses, do a Global Fit to all the spectra together with the positions and the FWHM coefficients linked between spectra. Then Global Fit will find the best position and FWHM for all spectra together.

It does mean that you must prepare a fitting function that will fit the appropriate number of peaks for a given set of spectra.

In reply to by johnweeks

Thank you for the comment,

That's what I was also planning to do. I was trying to use one spectrum and do the curve fitting for that by a user-defined function. I have posted the equation I used but it doesn't give me a good outcome.(At least for now....)

If you want help with the original problem (we seem to be coming back around to that) it would be best if you can post an Igor experiment file with the data and your fitting function in it. That way we can all try it out and give you specific guidance. If you can't post the data because of  security concerns, you could send it to and I will take a look at it. Our support never shares any data customers send us. If you request it, we will erase anything you send after we have resolved your problem.

A low-tech option when you have multiple datasets with peaks at the same positions is to add all the datasets together. This gives you a single spectrum with all peaks present and very good signal-to-noise ratio. You can now fit this combined spectrum to find the positions and shapes of all the peaks and use these positions and shapes to fit the individual datasets.

It's less elegant than doing global fitting, but it's a way to sometimes bypass global fitting if that is giving you a headache.

Heh. Global Fit does exactly that, olelytken. The thing Global Fit does is to add fancy bookkeeping and coefficient dispatching to the fit function to handle the arbitrary coefficient linkages. But if you use Global Fit with several data sets, with all coefficients linked to the same coefficients across data sets, it is exactly concatenating all the data sets to fit simultaneously.

John, I think that olelytken's suggestion is to add the waves, not concatenate like in global fit. If peaks are reasonably well separated that could be a good starting point.

When there is significant overlap in peaks so that they are better defined in one wave that in the sum of waves it might be less useful.