
Normalized Derivative Peak Functions

harneit
As a "pedestrian" alternative for those preferring command-line operations, here's a collection of properly normalized peak fitting functions often used in spectroscopy: Gaussian, Lorentzian, and pseudo-Voigt shapes; both for normal and derivative peaks.
There are four versions for each shape: two versions have the visible amplitude of the peak as the intensity parameter, which makes providing good guesses easier. The other two have the integrated area as the intensity parameter (useful for estimating scattering strength, analyte concentrations, etc.). Each of these variants are available either for absorption or for derivative line shapes. For the absorption shapes, the width parameter is the FWHM while for the derivative peaks, it is the peak-to-peak width.
For more detail, see the documentation in the code. It also explains how to use these functions with
FuncFit
's cool feature of "fitting sums of functions". The functions provided here have no constant term, so it is not necessary to hold those terms in order to avoid the "linear-dependency" problem. Rather, one could add another fitting function (e.g., lin) to simultaneously fit the background.I checked the formulae used in these functions thoroughly but if you detect errors, please let me know.
#pragma rtGlobals=1 // Use modern global access method. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Normalized peak functions (Gauss, Lorentz, pseudo-Voigt) in absorption and dispersion mode. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // by W. Harneit (Berlin), November 2009 // August 2010: Updated comments, included note on multi-peak fitting // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Each function takes three parameters (in wave w): intensity, position, and width. // // For the ...Amp functions, the intensity parameter means amplitude (from zero). // The area is not normalized in this case. // For the ...Area functions, intensity means integrated area (or double integral for Diff...). // The intensity parameter does not correspond to the peak amplitude in this case. // // For the absorption functions (without Diff...), width means full width at half maximum (FWHM). // The Diff... functions are the derivatives (dispersion mode). Width is peak-to-peak width (p.p. width). // p.p. width (dispersion) and FWHM (absorption) are linearly related, depending on the peak form. // // The Pseudo-Voigt functions are a simple linear interpolation between Gauss and Lorentz form, with // _equal_ width. They take a fourth parameter 0 <= w[3] <= 1, which is the weight of the Lorentzian // (the weight of the Gaussian is 1 - w[3]). Strange things will happen if w[3] > 1. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Examples: // // GaussAmp is the absorptive Gaussian, with amplitude w[0], position w[1], fwhm w[2]. // // DiffLorArea is the dispersive Lorentzian, with double integral w[0], position w[1], p.p. width w[2]. // // To do multi-peak fitting, follow the steps below. // (see also DisplayHelpTopic "Fitting Sums of Fit Functions") // // We assume that a two-line absorption spectrum is present in spec_INT. The position parameters // are the most sensitive parameters, followed by the width. Intensities (here: areas) may be way off. // Tip: You can use "Decommentize" (Edit menu) on the following lines. // // // Step 1: provide guesses for the two peaks // Make/D/O low={4e-10,0.33707,2e-5}, high={4e-10,0.33818,2e-5, 0.77} // // Step 2: provide hold strings (if any) // String hstr = "0001" // to hold the shape parameter p=0.77 for the "high" peak // // Step 3: do the fit // FuncFit/M=0/L=4096/W=0/X {{LorArea,low}, {PseudoVoigtArea,high,hold=hstr}}, spec_INT /D // // /M=0 => no cov. matrix; /L= numpnts; /W=0 => don't wait; /X => full X range; /D => auto dest. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // code note: Numerical constants are given in the comments with 5 digits precision. // If speed is an issue, one could use global constants "constant kln2 = 0.69315" etc. // function GaussAmp(w, x) wave w variable x variable xi = 2 * (x - w[1]) / w[2], ln2 = ln(2) // ln2 = 0.69315 return w[0] * exp(-ln2*xi*xi) end function GaussArea(w, x) wave w variable x return GaussAmp(w, x) / ( sqrt( pi / ln(2) ) / 2 * w[2] ) // divisor = 1.0645 * w[2] end function LorAmp(w, x) wave w variable x variable xi = 2 * (x - w[1]) / w[2] return w[0] / (1 + xi*xi) end function LorArea(w, x) wave w variable x return LorAmp(w, x) / ( pi / 2 * w[2] ) // divisor = 1.5708 * w[2] end function DiffGaussAmp(w, x) wave w variable x variable xi = 2 * (x - w[1]) / w[2], ln2 = ln(2) // ln2 = 0.69315 return -xi * w[0] * exp(-0.5*(xi*xi-1)) end function DiffGaussArea(w, x) wave w variable x return DiffGaussAmp(w, x) / ( sqrt( pi * e / 8 ) * w[2] * w[2] ) // divisor = 1.0332 * w[2]^2 end function DiffLorAmp(w, x) wave w variable x variable xi = 2 * (x - w[1]) / w[2] return -xi * w[0] * ( 4 / (3 + xi*xi) )^2 end function DiffLorArea(w, x) wave w variable x return DiffLorAmp(w, x) / ( sqrt( 4 / 3 ) * w[2] * w[2] ) // divisor = 1.1547 * w[2]^2 end function PseudoVoigtAmp(w, x) wave w variable x return w[3] * LorAmp(w, x) + (1 - w[3]) * GaussAmp(w, x) end function PseudoVoigtArea(w, x) wave w variable x return w[3] * LorArea(w, x) + (1 - w[3]) * GaussArea(w, x) end function DiffPseudoVoigtAmp(w, x) wave w variable x return w[3] * DiffLorAmp(w, x) + (1 - w[3]) * DiffGaussAmp(w, x) end function DiffPseudoVoigtArea(w, x) wave w variable x return w[3] * DiffLorArea(w, x) + (1 - w[3]) * DiffGaussArea(w, x) end

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More