How can I calculate a mean value of peak amplitude and area under the curve?

90 views (last 30 days)
Hello,
I hope someone can help me with my problem. As a healthcare professional, I lack the basic understanding of Data programming and mathematics.
I have a recording of, how the absorption varies, from an infrared photoplethysmography signal obtained in vivo. The data is imported in Matlab as column vectors. I have managed to apply a low pass and a bandpass filter to the raw signal, separating the different components I have to analyse further. From the band pass filtered signal (picture below), I need to – for a number of given time points (illustrated with a green arrow):
- Determine the peak amplitude (local minima to the peak).
- Determine the area under the curve (AUC) – from minima to the peak.
- The amplitude and AUC should be estimated with some mean value, e.g. +/- 5 seconds from the given time point or +/- 5 peaks. I don’t know which of them is the best method?
Does anyone have any suggestions for possible solutions?
I appreciate any help you can provide.
Y-axis: light absorption in arbitrary units, X-axis: time, based on sampling rate (100 Hz) – every second = 100 units
  2 Comments
Dyuman Joshi
Dyuman Joshi on 15 Feb 2023
Do you have to find the amplitude and AUC for every peak? or just corresponding to the global maximum peak?
Erik Näslund
Erik Näslund on 15 Feb 2023
I need to find amplitude/AUC for every peak, surrounding a given time point, and calculate a "local" mean.

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 15 Feb 2023
It always helps to have a signal to work with, so I found one from a previous pulse-plethysmograph post and am using it here. (All the pre-processing steps may not be necessary for your signal, however they were for this one. They also demonstrate how to pre-process a physiological signal in general.)
Try something like this —
PPG = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/103608/p3_sit.csv'); % Use PPG Signal From Previoous Answer
PPG = PPG(PPG>=1E+6); % Remove Artefacts (This Signal Only)
L = size(PPG,1)
L = 449359
Fs = 960;
Fn = Fs/2;
t = linspace(0, L-1, L)/Fs; % Time Vector
t = t(:); % Force Column Vector
NFFT = 2^nextpow2(L)
NFFT = 524288
FT_PPG = fft((PPG-mean(PPG)).*hann(L),NFFT);
Fv = linspace(0,1,NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FT_PPG(Iv)*2))
grid
xlim([0 10])
PPG = lowpass(PPG, 5, Fs, 'ImpulseResponse','iir'); % Remove High-Frequency Noise (This Signal Only)
PPGmax = max(PPG);
PPGmin = min(PPG);
[pks,plocs] = findpeaks(PPG, 'MinPeakProminence',(PPGmax-PPGmin)*0.05); % Peaks
[vys,vlocs] = findpeaks(-PPG, 'MinPeakProminence',(PPGmax-PPGmin)*0.05); % Valleys
for k = 1:numel(vlocs)-1
idxrng = vlocs(k) : vlocs(k+1); % Index Range For This Pulse
idxlim = [vlocs(k); vlocs(k+1)]; % Inmdex Limits
tv = t(idxrng); % Pulse 't' Vector
sv = PPG(idxrng); % Pulse 'PPG' Vector
ts(k,:) = t(vlocs(k)); % Pulse Start Time
te(k,:) = t(vlocs(k+1)); % Pul;se End Time
kv(k,:) = k; % Peak Counter
B = [t(idxlim) ones(2,1)] \ PPG(idxlim); % Linear Detrending Regression Parameters
dtsv = [t(idxrng) ones(size(t(idxrng)))] * B; % Linear Detrending Vector
svc = sv - dtsv; % Detrended Signal
p2p(k,:) = max(svc); % Peak-To-Peak Amplitude
AUC(k,:) = trapz(tv,svc); % Pulse Area
end
PPG_Statistics = table(kv,ts,te,p2p,AUC, 'VariableNames',{'Peak','t_start','t_end','PeakToPeak','AUC'})
PPG_Statistics = 533×5 table
Peak t_start t_end PeakToPeak AUC ____ _______ ______ __________ __________ 1 0.35625 1.0615 2.1852e+05 68335 2 1.0615 1.9187 2.0586e+05 74229 3 1.9187 2.701 2.8195e+05 94319 4 2.701 3.4365 3.6124e+05 1.0798e+05 5 3.4365 4.2542 4.7608e+05 1.4338e+05 6 4.2542 5.1667 5.3515e+05 1.7238e+05 7 5.1667 6.025 5.2727e+05 1.6454e+05 8 6.025 6.7417 3.9724e+05 1.3015e+05 9 6.7417 7.7635 3.4405e+05 1.4125e+05 10 7.7635 8.6667 3.2516e+05 1.2902e+05 11 8.6667 9.601 2.6599e+05 1.0231e+05 12 9.601 10.455 2.0859e+05 75130 13 10.455 11.417 2.6815e+05 1.0332e+05 14 11.417 12.381 3.687e+05 1.4273e+05 15 12.381 13.354 4.8558e+05 1.8557e+05 16 13.354 14.235 4.9775e+05 1.7913e+05
figure
hp{1} = plot(t, PPG, 'DisplayName','PPG Data');
hold on
hp{2} = plot(t(plocs), pks, '^r', 'DisplayName','Peaks');
hp{3} = plot(t(vlocs), -vys, 'vr', 'DisplayName','Valleys');
hp{4} = plot((t(plocs(1:numel(p2p)))*[1 1]).', [pks(1:numel(p2p)) pks(1:numel(p2p))-p2p].', '-k', 'DisplayName','Peak-Peak');
hp{5} = plot(t(vlocs), -vys, '-g', 'DisplayName','Inter-Valley Baseline');
hold off
grid
legend([hp{1}(1),hp{2}(1),hp{3}(1),hp{4}(1),hp{5}(1)],'Location','best')
xlim([0 10]) % Zoom To See Details
I have no idea what the original units were for this signal, however the values for the derived statistics appear to be correct.
Try my code with your signal. If there are any problems, I will help adapt my code to it.
.
  10 Comments
Erik Näslund
Erik Näslund on 14 Jun 2023
Ah - It was that simple. Adjusted the factor multiplying MinPeakProminence - value to 0.05, and after that MATLAB has not, so far, misinterpreted the curve.
I have been very happy with your code so far! With this modification, it's an easy fix re-running the script for those recordings needing adjustment.

Sign in to comment.

More Answers (1)

Aman
Aman on 15 Feb 2023
Hi,
I understand that you have a function, and you want to find out its global maxima. Then you want to find the nearest local minima on the either side of the global maxima and then calculate the area between the two local minima.
For finding the global maxima you can use the “max” function. Upon getting the global maxima you can use the “islocal” function to get all the local minima, upon getting all the local minima you can find the nearest local minima on the either side of the global maxima. Once you get the local minima of the either side you can find the subsection between them and then use the ”trapz” function to get the area between them. You can refer to the following example:
x = 1:100;
A = (1-cos(2*pi*0.01*x)).*sin(2*pi*0.15*x); % objective function
[maxVal,indx] = max(A); % global maxima
TF = islocalmin(A); % all local minima
for i=indx:-1:1
if(TF(i))
localMinLeft = i;
localMinLeftVal = A(i); % local minima to the left of the global maxima
break;
end
end
for i=indx:100
if(TF(i))
localMinRight = i;
localMinRightVal = A(i); % local minima to the right of the global maxima
break;
end
end
subSection = A(localMinLeft:localMinRight); % subsection between the local minimas
plot(x,A);
hold on;
plot(localMinRight,localMinRightVal,'r*');
plot(localMinLeft,localMinLeftVal,'r*');
plot(x(indx),A(indx),'bo');
plot(localMinLeft:localMinRight,subSection);
hold off;
disp('Area under the curve is ' + trapz(subSection)); % area under the subsection selected
Hope this helps!
  1 Comment
Erik Näslund
Erik Näslund on 15 Feb 2023
Thank you very much for your answer, which is elegant. To clarify, I don't have a function to work with (?), but rather an imported column vector to MATLAB. In this vector, I need to, for X number of time points, find a mean estimate of AUC/peak amplitude at each time point.
Is your solution applicable to such a problem?
Thank you!

Sign in to comment.

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!