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

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More