Spectral decomposition as a sum of sub-spectra
PASQUIER
I would like to fit a spectrum (Stot) as the sum of several sub-spectra (SA, SB) like Stot = (1-k) SA + k SB
All the spectra Stot, SA and SB are known. But in this case, there are no independent variables, there is only one fit parameter, k.
The problem seems very simple, but I'm at a bit of a loss as to how to fix it.
Thank you for advance for any advice.
Hélène
PS : Stot, SA and SB have the same x scaling and are waves of same size.
File--> Example Experiments -->Curve Fitting -->Multi Variate Fit Demo
April 17, 2016 at 08:39 pm - Permalink
Wave SA, SB
MultiThread wy=(1-wc[0])*SA+wc[0]*SB
End
Most likely you will need to constrain wc[0] between 0 and 1; or at least check the result manually.
Here is an example of fitting a signal comprising two measured response functions with variable offset, individual intensity, and individual time shift:
Wave wc, wy, wx
Wave LO=root:NAC:Experiment:FitLaserReferenceOdd, RO=root:NAC:Experiment:FitRadiationOdd
MultiThread wy=wc[0]+wc[1]*LO(x-wc[2])+wc[3]*RO(x-wc[4])
End
HJ
April 18, 2016 at 02:31 am - Permalink
many thanks Austenld and HJDrescher for your reply.
I'm sorry HJDrescher, I am not used to playing with multithreads. i use only Macro and function. It is perhaps why Igor doesn't want to compile the function
Function CalorimetryOdd(wc,wy,wx):Fitfunc
you proposed me. I have the Igor 6.0 version.
However, in your exemple, It seems that your function is still depending on a independent variable x.
My problem is that basically my spectra haven't analytical expression depending on an independent variable x.
Of course, it would be possible to give them an analytical expression depending on x if i fit my spectra by using the Multi-peak fitting panel. But by this way, i introduce bias since the fit is not totally perfect which is why I posed the question : how to decompose a spectrum as the sum of sub-spectra.
Helene
April 20, 2016 at 02:31 pm - Permalink
A compilation error is rather expected since you most likely do not have the same experiment structure (a slightly more complex example for adaptation).
My data points are spaced by milliseconds and I want to use SI units. Hence, I'm using x and not p scaling; note that I don't use wx. The full wave range ('all data points') is calculated and returned. x by itself does not matter, it is only used to shift the whole data sets with respect to another. Otherwise p-scaling would also work and no x would show up in the function.
The fitting data sets are neither analytical nor perfect in my case. Real data with arbitrary shape, noise, artifacts, and everything you usually don't want to have in a fitting routine. It still works. In the attached image, the green and blue traces are an offsetted, weighted sum of the purple and the orange trace (using the 'calorimetry' functions -- x-shifts constrained to zero in this case).
Waves always have an intrinsic scaling (by default data points have a distance of 1 yielding x=p; in your case wavenumbers). Have a look at 'setscale'. Actually you don't need the wave 'wavenumber'.
The function should look like this:
Wave wc,wy,wx
wave SA, SB
wy=(1-wc[0])*SA+wc[0]*SB
End
Note that the source spectra are not passed as wave parameters!
Create a coefficient wave
make /N=1 /O wc=0.1
and use the standard Analysis->Curve Fitting Dialogue with 'Partition2fct' as function, y-data: Sessai, and coefficient wave 'wc'.
I got k0=0.15 which matches exactly the definition of sessai.
HJ
April 20, 2016 at 04:50 pm - Permalink
You are the best !!! It is wonderful, it works ! Many Thanks.
Now I can change the fitfunction as I want !
Yes I really agree with you. It is just a matter of time, to understand how it works, what are the changes in programming between macro, function and multithread.
Yes you're right, It is what i use usually (setscale)
Have a nice and quiet night
Helene
April 21, 2016 at 01:44 pm - Permalink
Hi all,
The approach seems to work for me as well. I have a couple of questions though.
- How does it work? Is it a least squares fitting?
- How can I define constraints? Say, I want parameter "a" to be bound in the 0 to 1 range, or for it to be positive. How do I do that?
Thanks
FYI, here is the function I am using:
Wave par, y, x
Wave C1, C2, C3
MultiThread y = par[0] + par[1]*C1(x) + par[2]*C2(x) + par[3]*C3(x)
end
January 17, 2019 at 08:24 am - Permalink