
A fit function for QENS data.

andyfaff
Function fitUsingNLor(cw, yw, xw1) : FitFunc Wave cw, yw, xw1 //An all at once fit function to fit QENS data. //function fits a linear background // with a delta function // and N lorentzians. // delta and lorentzians are centred at the same position (cw[2]) // xw1 contains the x values // res contains the instrumental resolution function at the same x values. // the returned y wave consists of the sum of the delta and N lorentzian functions // convolved with the resolution function //the resolution function MUST be contained in the following wave Wave res = root:res //!!!!!!!!!!!!!! //ASSUMES: //1) THAT THE POINT SPACING IN XW1 IS LINEAR!!!!!!!!!!!!!!!!! //2) THE RESOLUTION WAVE MUST HAVE THE SAME NUMBER OF POINTS AS XW1 AND BE THE WAVE ROOT:RES //3) DO NOT TRY TO INTERPRET THE FUNCTION AT ANY OTHER POINTS THAN THE INPUT XW1 WAVE (IT DOESN'T MAKE SENSE). //!!!!!!!!!!!!!! //explanatory //cw[0] = a //cw[1] = b //cw[2] = PEAK POS //cw[3] = area - delta //cw[4] = FWHM - lor 0 //cw[5] = AREA - lor 0 //cw[2*n + 4] = FWHM - lor n //cw[2*n + 5] = AREA - lor n variable timer variable numconts, ii, offset, area_res, conv_offset, rot_remaining, shift, thearea numconts = (numpnts(cw) - 4)/2 yw = 0 make/free/d/n=3 lor_cw = 0 make/free/d/n=(numpnts(yw)) tempyw MarkPerfTestTime 0 for(ii = 0 ; ii < numconts ; ii+=1) offset = 2*ii + 4 lor_cw[0] = cw[2] lor_cw[1] = cw[offset] lor_cw[2] = cw[offset + 1] //multithread tempyw = 2*lor_cw[2]/pi * lor_cw[1]/(4*(xw1-lor_cw[0])^2 + lor_cw[1]^2) MPFXLorenzianPeak(lor_cw, tempyw, xw1) multithread yw += tempyw endfor MarkPerfTestTime 1 //convolve and account for the scaling convolve/a res, yw MarkPerfTestTime 2 fastop yw = (xw1[1] - xw1[0]) *yw theArea = areaXY(xw1, res) fastop yw = (1/theArea) * yw MarkPerfTestTime 3 //have to rotate because of the convolution //the rotate operation gets you most of the way there conv_offset = binarysearchinterp(xw1, 0) - trunc(numpnts(xw1) / 2) rotate -trunc(conv_offset), yw duplicate/free yw, tempyw rot_remaining = conv_offset - trunc(conv_offset) yw = tempyw[p + rot_remaining] MarkPerfTestTime 4 //add in scaling of the delta function duplicate/free res, tempyw shift = cw[2]/(xw1[1] - xw1[0]) area_res = areaxy(W_energy, res) yw += tempyw[p-shift] * cw[3] / area_res //add in the background multithread yw += cw[0] + cw[1] * xw1 MarkPerfTestTime 5 End

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
I wrote the following comments before I realized it was you... I'm sure you've thought about these issues... People reading my comments should not take them to indicate that they should avoid using this code!
"//ASSUMES THAT THE POINT SPACING IN XW1 IS LINEAR!!!!!!!!!!!!!!!!!"
It might also cause problems using the /D auto-destination feature.
You can most likely relieve that requirement by (carefully) making an intermediate wave to gather computed results, then using a wave assignment to read out linearly-interpolated values into the yw wave. See the second example here:
DisplayHelpTopic "All-At-Once Fitting Functions"
I am concerned about your use of a second independent variable to pass in the resolution function. That will make Igor think this is a multivariate fit function and /D flag will be made as a matrix. Your solution is easy to use, of course, since you can do it all in the Curve Fit dialog. But you would be better off to write a driver function and pass the resolution function via a wave that's looked up use a WAVE statement inside the function. You could also do this via a structure-based all-at-once fit function:
DisplayHelpTopic "Structure Fit Functions"
Since Igor is not able to make global structures, you *have* to make a driver function for the fit.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 7, 2011 at 09:27 am - Permalink
If you know a better way to do the convolution please let me know.
April 7, 2011 at 08:57 pm - Permalink
My solution to convolution of non-evenly-spaced data is to make an intermediate wave that *is* evenly spaced and do all the computations using that. Then the last line is an interpolation into the yw wave. That's the way the convolution all-at-once complicated example works. It can be really tricky to figure out a heuristic for making an adequate intermediate wave.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 8, 2011 at 09:53 am - Permalink
March 1, 2014 at 01:54 pm - Permalink
Does this make sense?
So, at least I can now get the function to return something that seems workable. But, when I go to fit my QENS data what is returned as the fit wave has odd x scaling and the doesn't fit the data. It is broadened and too tall by 1-2 orders of magnitude. I have attached a image of the fit window with the resolution wave, test data wave, fit wave, and the wave I create with the fit parameters.
I think there is still something wrong.
Suggestions?
Dean
March 1, 2014 at 04:41 pm - Permalink