How to calculate the FWHM from multiple spectra?
4 views (last 30 days)
I have been looking over the documentation for findpeaks and several FWHM scripts, but I am not having any luck.
I have multiple .csv files of a single peak of Raman data, with the magnitude and wavelength. I would like to have a script that reads each .csv file and calculate the FWHM of the peak.
I currently have a script that reads my .csv files from a folder and spits out information such as peak postion, area etc., so maybe its easier to just tag it onto that, however it is using peakfit, not fitpeak. I have inserted below the section of the script which fits the peaks.
% Code for reading in files is above here!
% Now go through all the files in that folder and apply signal processing.
% Skip any files that generate and error and keep going.
datamatrix=load([DataDirectory '\' fn(FileNum,1:NameLength)]);
DataArray=[datamatrix(:,1) datamatrix(:,2)]; % Change to suit format of data
disp([num2str(FileNum) ': ' fn(FileNum,1:NameLength)])% Prints out the file number and name
disp(' Peak# Position Height Width Area')
% Curve fitting settings:
windowcenter=0; % Change this to fit other regions of the spectrum
windowwidth=0; % Change to zoom in or out to smaller or larger region.
NumPeaks=15; % Change this to the expected number of peaks.
Shape= 4; % 1-Gaussian, 2-Lorentzian, etc. Type "help peakfit" for list.
NumTrials=10; % Usually 1 to 10. Lower numbers faster but less stable.
startvector=0; % Difficult cases may require start vector, see help file.
BaselineMode=0; % Can be 0, 1, 2,or 3 (1=linear baseline subtraction)
disp(' % fitting error R2')
% Add code here if you want to perform another set of
% operations on the same data file with different settings, i.e.,
% different data region, number of peaks, peak shape, etc.
disp([ num2str(FileNum) ': Error encounted with file: ' me.identifier])
(I cannot remember who to credit with the above code, as I found this many months ago!)
Would it be best to just tag a FWHM code into this script, or write something completely separate?
Thanks in advance.
EDIT: Addition of example data.
Star Strider on 20 Jun 2022
Edited: Star Strider on 20 Jun 2022
It might be easier if we had one or two typical .csv files to experiment with.
The findpeaks WidthReference option is 'halfprom' by default, although it can be set to 'halfheight' to calculate the FWHM value. If baseline offset or an inconstant baseline is a problem, there are several ways to deal with that.
EDIT — (20 Jun 2022 at 14:12)
Do you want to detrend the baseline first? If so, that is relatively straightforward —
D = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1039090/example.csv');
[~,ixu] = unique(D(:,1));
x = D(ixu,1);
y = D(ixu,2);
B = [x([1 end]) ones(2,1)] \ y([1 end]);
ydt = [x ones(size(y))] * B;
ybc = y-ydt; % Baselilne Corrected
It would be difficult to fit Gaussian peaks to this because the peak contributions are not well-defined. Calculating the FWHM of the single peak however would be relatively straightforward.
[pkmax,ixp] = max(ybc);
ixv = find(diff(sign(ybc-(pkmax/2))));
for k = 1:numel(ixv)
idxrng = max(1,ixv(k)-1) : min(numel(x),ixv(k)+1);
xv(k) = interp1(ybc(idxrng), x(idxrng), pkmax/2);
yv(k) = interp1(x(idxrng), ybc(idxrng), xv(k));
plot(xv, yv, '+r')
text(x(ixp),pkmax/2, sprintf('\\leftarrow FWHM = %.1f \\rightarrow', diff(xv)), 'Horiz','center', 'Vert','middle', 'FontSize',7)
Make appropriate changes to get the result you want.