# Spectral decomposition as a sum of sub-spectra Hi,

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.

I think k=wc is your independent variable (although it looks more like a parameter) in this case:
Function Partition(wc,wy,wx):Fitfunc
Wave SA, SB
MultiThread wy=(1-wc)*SA+wc*SB
End

Most likely you will need to constrain wc 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:
Function CalorimetryOdd(wc,wy,wx):Fitfunc
Wave wc, wy, wx
Wave LO=root:NAC:Experiment:FitLaserReferenceOdd, RO=root:NAC:Experiment:FitRadiationOdd
MultiThread wy=wc+wc*LO(x-wc)+wc*RO(x-wc)
End

HJ
Hi,
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

Multithread in combination with the all-at-one fit function is only speeding things up -- and in your case I would start to recommend it.
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:
Function Partition2fct(wc,wy,wx):Fitfunc
Wave wc,wy,wx
wave SA, SB
wy=(1-wc)*SA+wc*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
Hi HJDrescher,

You are the best !!! It is wonderful, it works ! Many Thanks.
Now I can change the fitfunction as I want !

HJDrescher wrote:
Multithread in combination with the all-at-one fit function is only speeding things up -- and in your case I would start to recommend it.

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.

HJDrescher wrote:
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'.

Yes you're right, It is what i use usually (setscale)

Have a nice and quiet night
Helene

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:

Function LinearCombination3C(par, y, x) : FitFunc
Wave par, y, x
Wave C1, C2, C3
MultiThread y = par + par*C1(x) + par*C2(x) + par*C3(x)
end