User Defined Peak Shape in Multipeak fitting 2.0

Hi everyone,

I was hoping to add a user defined peak shape to my multipeakfitting 2.0 toolbox, but I am struggling to understand how to do thins. I have looked into the Peakfunctions2.ipf macro that has the peak functions, but I am unsure how to go about adding my own function. If someone could walk me through doing this, or may already have this peak shape written into a macro that they are willing to share I would appreciate it.

The function I want to add is a Breit–Wigner Fano peak shape. This is an asymmetric peak that is pretty common when looking at Raman spectroscopy of amorphous carbons. The function is as follows, sorry for the horrible formatting of the equation here.

I(ω) = (A/(1+(2(ω+ω)/T)^2)) + B[1+2((ω- ω2)/qT2)]2/[1+2((ω- ω2)/T2)]2.

Any help or guidance on how to properly get this added to my fitting options would be appreciated.

Thanks
Yeah, Multipeak Fit 2 makes it possible to add your own peak shapes, not easy to do so.

I started looking at the problem and I think your equation has a typo in it. Should this: 2(ω+ω) be something more like 2(ω-ω2)? I guess ω2 is what is commonly rendered as x0.

And can you give me some info on what controls width and amplitude?

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Yes, it is not extremely easy, but if you understand how it works it is rather straight-forward. You basically need to write four functions:
1) a function for naming you input/output parameters, as well as telling MPF the names of the other three functions.
2) a function calculating the shape of you peak using an x & y-wave input and a parameter set
3) a function calculating useful initial guesses from the standard asymmetric gaussian (the shape you draw when adding a peak) handed from MPF, or at least plug in the ones like width, height at the right places for your peak to work
4) a function calculating useful output parameters from you fit parameters (i.e., FWHM from width etc.). If you feel lazy just hand over the fit parameters and do the rest later.
Peeking at the at the already implemented one's (PeakFunctions2.ipf) might help a bit to get a grasp how stuff works. Also, you might want to read here a bit: http://www.igorexchange.com/node/5750
I attach my definition of the Doniac-Sunjic peak-shape for reference (this one is already rather advanced, as it involves Gauss-convolution to simulate experimental broadening, so please don't feel demotivated by this).


//________________________________________________________________________________________________//
//	MultiPeak-Fit function:	Doniac-Sunjic shape
//________________________________________________________________________________________________//

Function/S DS_PeakFuncInfo(InfoDesired)
	Variable InfoDesired
 
	String info=""
 	Switch (InfoDesired)
		case PeakFuncInfo_ParamNames:
			info = "Location;Width;Height;Asymmetry;GaussW;"
			break;
		case PeakFuncInfo_PeakFName:
			info = "DSPeak"
			break;
		case PeakFuncInfo_GaussConvFName:
			info = "GausstoDSGuess"
			break;
		case PeakFuncInfo_ParameterFunc:
			info = "DSParams"
			break;
		case PeakFuncInfo_DerivedParamNames:
			info = "Location;Height;Area;FWHM;Asymmetry;GaussWidth;"
			break;
		default:
			break;
	endSwitch
 	return info
End
//################################################################################################
Function DSPeak(w,yw,xw)
	Wave w
	Wave yw, xw
 
 	Variable Resolution	= 10								 // the sample resolution (higher = slower)
	Variable Xdelta		= abs(xw[0] - xw[NumPnts(xw)-1]) / (Resolution * NumPnts(xw))		 // calculate an high-res xdelta for scaling
	Variable yPoints	= Resolution * NumPnts(yw)			 // make the wave X times bigger than the original y wave
	Make/FREE/D/N=(2*yPoints+1) yWave						 // create a wave two times as big to have space before and after the peak
	SetScale/P x xw[0]-yPoints/2*Xdelta, Xdelta, yWave			 // reserve 1/2 size of space before the x wave starts (1/2 after)
 
	yWave = w[2]*cos(Pi*w[3]/2+(1-w[3])*atan((x-w[0])/w[1]))/((x-w[0])^2+w[1]^2)^((1-w[3])/2)
	
	PeakConvolveGauss(yWave, w[4])
	
	yw = yWave(xw[p])		 // write the calculated values into the resultwave
End
//################################################################################################
Function GaussToDSGuess(w)
	Wave w
	
	Variable x0	= w[0]	 // extract the initial guesses
	Variable width	= w[1]
	Variable height	= w[2]
	Variable lwidth	= w[3]
	Variable rwidth	= w[4]
	
	Redimension/N=5 w		 // redimension to apropriate values
	// output values are: "Location;Width;Height;Asym;GaussW;"
	w[1] = 0.8*width	 // 80% into lorentzian width
	w[2] = 0.8*height	 // make the peak a bit smaller
	w[3] = 5*(rwidth-lwidth)/width	 // asymmetry depending on width difference
	w[4] = 0.3*width	 // 30% into gaussian width
	return 0
end
//################################################################################################
Function DSParams(cw, sw, outWave)
	Wave cw, sw, outWave

	Variable Amplitude, Location, FWHM, PeakArea
	Peak_FindStats(cw, "DSPeak", Amplitude, Location, PeakArea, FWHM) // approximately calculates all the results from the parameters

	Redimension/N=(6,2) outWave
	// output values are: "Location;Height;Area;FWHM;Asym;GaussWidth"	
	outWave[0][0] = Location				 // position
	outWave[0][1] = sqrt(sw[0][0])
	outWave[1][0] = Amplitude				 // height
	outWave[1][1] = NaN					 // no idea how to calculate the error
	outWave[2][0] = PeakArea				 // area (probably wrong)
	outWave[2][1] = NaN
	outWave[3][0] = FWHM				 // FWHM
	outWave[3][1] = NaN
	outWave[4][0] = cw[3]				 // asymmetry value
	outWave[4][1] = sqrt(sw[3][3])
	outWave[5][0] = cw[4]				 // gauss broadening width
	outWave[5][1] = sqrt(sw[3][3])
End
//###################################### Value finder helper function ###################################
Function Peak_FindStats(cw, PeakFunc, Amplitude, Location, PeakArea, FWHM) // recalculate the FULL peak and extract all result values (approximately)
	Wave cw
	String PeakFunc
	Variable &Amplitude, &Location, &PeakArea, &FWHM
	
	Funcref PCISimplePeak PeakFunction = $PeakFunc		 // reference the passed peak function
	
	Variable x0	= cw[0]
	Variable width	= cw[1] + cw[4]
	Variable PosH	= cw[2] > 0				 // Look if height is positive
	
	Variable Size = 3000						 // create a big wave (fine increments)
	Make/FREE/N=(Size+1) yw, xw
	xw = (p/Size-0.5) * 30 * width + x0			 // create a broad x scale (to make sure the full peak fits in)
	PeakFunction(cw, yw, xw)					 // recalculate the peak with the coef set
	WaveStats/Q yw							 // find the statistics

	if (PosH)
		Amplitude	= V_max
		Location	= xw(V_maxloc)
	else
		Amplitude	= V_min
		Location	= xw(V_minloc)
	endif
	
	FindLevel/Q/R=(0,Size/2) yw, Amplitude/2
	Variable Left	= V_flag == 1 ? NaN : xw(V_LevelX)
	FindLevel/Q/R=(Size/2,Size) yw, Amplitude/2
	Variable Right	= V_flag == 1 ? NaN : xw(V_LevelX)	
	
	FWHM		= abs(Left -Right)
	PeakArea	= AreaXY(xw, yw)
	return 0
End