curve fitting and constraints

I have a several thousand datasets from which I want to subtract a quadratic background. (single example attached)

I think that the best way to do so is to fit a curve subject to an additional constraint that the value of the curve must be less than or equal to the data at every point.

The constraints make it easy to constrain the value of the coefficients, but I can't see how to further constrain based on the actual data values.

In Excel, I could add a column for the result of (data - calculated background) and have a single cell equal to the minimum of that column, and constrain the model such that the cell value is greater than or equal to zero.

.

Question: How can I constrain the model such that the model is always less than the data?
curveFit.pxp (43.63 KB)
You could use an approach similar to the one I posted here:
http://www.igorexchange.com/node/6006

In outline the process is as follows:
1. Fit your quadratic (or whatever function you desire) and calculate residuals.
2. Determine the data points that have the largest (positive) values for their residuals and mask these from subsequent fits.
3. Repeat 1 and 2 a few times.
The parameters are the number/fraction of points you exclude at each iteration, and the number of iterations.

The fit will then end up being on the background only (if the data is well behaved).
Note: there is a chance that a quadratic fit actually fits the peak initially - this is more likely to happen if there is more peak than background in your data. In this case, I suggest you make the first iteration a straight line fit.

HTH,
Kurt
I made it work, just not very elegantly. (apologies for making your eyes bleed)

Code to remove background from a 1 dimensional wave:

//in-place removal of BG.
function removeBG(withBG)
	wave withBG

	Make/D/O/N=(3) W_coef  // the same name as for CurveFit
	W_coef[0]=0.5 // offset
	W_coef[1]=0 // scale
	W_coef[2]=0 // scale
	
	Duplicate/O withBG, fitme, waveFit, diff  //these are the waves I need to fit the function
	
	variable i,j
	
	//this loop goes though and does a quadratic curve fit to the data
	//  after this, it finds the point that is the largest positive distance away
	//  from the curve and removes it from the calculation. It does this until 
	//  there are 4 points left, being one more than the degree of the curve.
	for(i = 0; i < numpnts(withBG) - 4; i+=1)
		CurveFit/Q poly 3, fitMe /D //fit the wave 
		for(j = 0; j < numpnts(waveFit); j += 1) //calc the value of the fit at each row value. there is probably an "igor way" of doing it, but I don't know it
			waveFit[j] = W_coef[0] + W_coef[1]*j + W_coef[2]*j^2
		endfor
		diff = fitme - waveFit //calc the difference plot
		WaveStats/Q diff //find the location of the max values
		fitme[V_maxRowLoc] = NaN //remove the points with the biggest positive difference
		diff[V_maxRowLoc] = NaN	
	endfor
	
	//One more curve fit with the last few points
	CurveFit/Q poly 3, fitMe /D 
	for(j = 0; j < numpnts(waveFit); j += 1)
		waveFit[j] = W_coef[0] + W_coef[1]*j + W_coef[2]*j^2
	endfor

	withBG = withBG - waveFit //withBG now has no BG
	
	//I don't need these, so I might as well clean them up
	KillWaves/Z fitme, waveFit, diff, W_coef, fit_fitme, W_sigma, W_ParamConfidenceInterval
end


code to apply the 1D case to a 2D wave of 1D waves that I need to fit:

function removeBGsurface(surf)
	wave surf
	variable ii,jj
	
	Make/O/N=(DimSize(surf,1)) wi
	
	for(ii = 0; ii < DimSize(surf, 0); ii += 1)
		print ii
		wi = surf[ii][p]
		removeBG(wi)
		
		//I can't figure out how to do the assignment in igor-speak
		for(jj=0; jj < DimSize(surf,1); jj += 1)
			surf[ii][jj] = wi[jj]
		endfor
	endfor
end



masheroz wrote:

		//I can't figure out how to do the assignment in igor-speak
		for(jj=0; jj < DimSize(surf,1); jj += 1)
			surf[ii][jj] = wi[jj]
		endfor


I think the following should work (not tested):

surf[ii][] = wi[q]

masheroz wrote:


		for(j = 0; j < numpnts(waveFit); j += 1) //calc the value of the fit at each row value. there is probably an "igor way" of doing it, but I don't know it
			waveFit[j] = W_coef[0] + W_coef[1]*j + W_coef[2]*j^2
		endfor


Oh, and also this should work (not tested):

waveFit[] = W_coef[0] + W_coef[1]*p + W_coef[2]*p^2