# Fit to complex-valued functions

The topic of fitting to complex-valued functions has come up in a couple of forum posts, http://www.igorexchange.com/node/2801 and http://www.igorexchange.com/node/1986, and a polished, complete XOP is available (Ellis 2, http://www.igorexchange.com/node/3126). Here is a bare-bones implementation that may be helpful for those wanting to understand how this works better or just to have a simple code to start from.

The first function, DoComplexFitMC, is a driver that generates fake data. It includes some code to help you graph the results. This is necessary as the default fitwave created does not separate real and imaginary parts and does not correctly assign x-ranges. The second function, ComplexFitAllAtOnce, is needed to match with the (real-only) expectations of FuncFit. The third function, ComplexFunc, contains the actual complex-valued function. You can easily modify this to fit your own needs.

Function DoComplexFitMC(ndat,a,b,sigma)          // driver to demonstrate fit to complex func
variable ndat,a,b,sigma                 // uses Monte Carlo (MC) to create fake data

make /c/d/free/n=(ndat) yw
make /d/free/n=(2*ndat) sigw
make /d/o/n=(2*ndat) ww2=0,yw2          // real waves for real and imag parts of yw, ww
variable wmax=30
ww2[0,ndat-1] = p/(ndat-1)*wmax         // linear span of frequencies  (often would be log...)
ww2[ndat, ] = ww2[p-ndat]               // these values are not used (dummy placeholders)

sigw = sigma                                    // wave of standard deviations
make /d/free pars={a,b}                     // pack true parameters into wave, use for fit, too
yw = ComplexFunc(pars,ww2)                  // noiseless "core"  for fit using true a,b
yw2[0,ndat-1] = real(yw)
yw2[ndat, ] = imag(yw[p-ndat])              // yw20 concatenates real & imaginary responses
yw2 += gnoise(sigma)                            // add noise for fake data (to be fit)

FuncFit/NTHR=0/W=2 ComplexFitAllAtOnce pars  yw2 /X=ww2 /W=sigw /I=1 /D       // does the fit

//_______________   graphics stuff__________________________
make /d/o/n=(ndat) yr,yi,w0                 //  waves for nice plotting
w0 = ww2[p]                                 // get first ndat points
yr = yw2[p];        yi = yw2[p+ndat]            // get real and imag parts

make /c/d/free/n=1000 fit_yc
make /d/o/n=1000 fit_yr, fit_yi
SetScale/I x 0,wmax,"", fit_yi,fit_yr,fit_yc
fit_yc = ComplexFunc(pars, x)
fit_yr=real(fit_yc);        fit_yi = imag(fit_yc)
End

Function ComplexFitAllAtOnce(pars,y2,w2) : FitFunc  // kluge for complex fits using FuncFit
wave pars,y2,w2
variable ndat = numpnts(w2)/2                       // break between real and imag data
make /c/d/free /n=(ndat) temp = ComplexFunc(pars,w2)                // call to complex fit func
y2[0,ndat-1] = real(temp);  y2[ndat, ] = imag(temp[p-ndat])     // concatenates real & imag
End

Function /c ComplexFunc(pars,w)
wave pars;  variable w
variable a=pars[0], b=pars[1]                       // unpack parameter wave
variable /c i=cmplx(0,1)                            // i = sqrt(-1)
return exp(i*w*a) / (1-i*w*b)                   // this is the function we fit!
end

Forum

Support

Gallery