SamuelNLP
SamuelNLP

Reputation: 4136

Define the width of peak in Matlab

I'm trying to find some peaks in Matlab, but the function findpeaks.m doesn't have the width option. The peaks I want to be detected are in the balls. All the detected are in the red squares. As you can see they have a low width. Any help?

enter image description here

here's the code I use:

[pk,lo] = findpeaks(ecg);

lo2 = zeros(size(lo));

for m = 1:length(lo) - 1
    if (ecg(m) - ecg(m+1)) > 0.025
        lo2(m) = lo(m);
    end
end

p = find(lo2 == 0);

lo2(p) = [];

figure, plot(ecg);
hold on
plot(lo, ecg(lo), 'rs');

Upvotes: 2

Views: 9149

Answers (4)

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38032

Thinking pragmatically, I suppose you could use something along the lines of this simple brute-force approach:

[peaks  , peakLocations]   = findpeaks(+X);
[troughs, troughLocations] = findpeaks(-X);

width = zeros(size(peaks));
for ii = 1:numel(peaks)

    trough_before = troughLocations( ...
        find(troughLocations < peakLocations(ii), 1,'last') );

    trough_after  = troughLocations( ...
        find(troughLocations > peakLocations(ii), 1,'first') );

    width(ii) = trough_after - trough_before;

end

This will find the distance between the two troughs surrounding a peak of interest.

Use the 'MinPeakHeight' option in findpeaks() to pre-prune your data. By the looks of it, there is no automatic way to extract the peaks you want (unless you somehow have explicit indices to them). Meaning, you'll have to select them manually.

Now of course, there will be many more details that will have to be dealt with, but given the shape of your data set, I think the underlying idea here can nicely solve your problem.

Upvotes: 1

user85109
user85109

Reputation:

You need to define what it means to be a peak of interest, and what you mean by the width of that peak. Once you do those things, you are a step ahead.

Perhaps you might locate each peak using find peaks. Then locate the troughs, one of which should lie between each pair of peaks. A trough is simply a peak of -y. Make sure you worry about the first and last peaks/troughs.

Next, define the half height points as the location midway in height between each peak and trough. This can be done using a reverse linear interpolation on the curve.

Finally, the width at half height might be simply the distance (on the x axis) between those two half height points.

Upvotes: 1

Eitan T
Eitan T

Reputation: 32930

You need to define a peak width first, determine how narrow you want your peaks to be and then select them accordingly.

For instance, you can define the width of a peak as the difference between the x-coordinates at which the y-coordinates equal to half of the peak's value (see here). Another approach, (which seems more appropriate here) is to measure the gradient at fixed distances from the peak itself, and selecting the peaks accordingly. In MATLAB, you'll probably use a gradient filter for that :

g = conv(ecg, [-1 0 1], 'same'); %// Gradient filter
idx = g(lo) > thr);              %// Indices of narrow peaks
lo = lo(idx);

where thr is the threshold value that you need to determine for yourself. Lower threshold values mean more tolerance for wider peaks.

Upvotes: 1

Alan
Alan

Reputation: 3417

By the looks of it you want to characterise each peak in terms of amplitude and width, so that you can apply thresholds (or simmilar) to these values to select only those meeting your criteria (tall and thin).

One way you could do this is to fit a normal distribution to each peak, pegging the mean and amplitude to the value you have found already, and using an optimisation function to find the standard deviation (width of normal distribution).

So, you would need a function which calculates a representation of your data based on the sum of all the gaussian distributions you have, and an error function (mean squared error perhaps) then you just need to throw this into one of matlabs inbuilt optimisation/minimisation functions.

The optimal set of standard deviation parameters would give you the widths of each peak, or at least a good approximation.

Another method, based on Adiel's comment and which is perhaps more appropriate since it looks like you are working on ecg data, would be to also find the local minima (troughs) as well as the peaks. From this you could construct an approximate measure of 'thinness' by taking the x-axis distance between the troughs on either side of a given peak.

Upvotes: 1

Related Questions