Asked by Matlaber
on 7 Feb 2019

Hi All,

I am trying to figure out how to cut out the specific segment of the signal where I draw the border using findpeaks function.

I am using example of findpeaks link below:

x = linspace(0,1,1000);

Pos = [1 2 3 5 7 8]/10;

Hgt = [4 4 2 2 2 3];

Wdt = [3 8 4 3 4 6]/100;

for n = 1:length(Pos)

Gauss(n,:) = Hgt(n)*exp(-((x - Pos(n))/Wdt(n)).^2);

end

PeakSig = sum(Gauss);

plot(x,Gauss,'--',x,PeakSig)

grid

Then, using findpeaks function,

findpeaks(PeakSig,x,'Annotate','extents','WidthReference','halfheight')

title('Signal Peak Widths')

I want to cut the segment of the border into 3 segment.

The method I am thinking is find the X value corresponding the Y value, which is not an effective way to do it.

Answer by Star Strider
on 8 Feb 2019

Accepted Answer

You can get the ‘Borders’ x-coordinates using:

(Previous Code)

findpeaks(PeakSig,x,'Annotate','extents','WidthReference','halfheight')

title('Signal Peak Widths')

Ax = gca;

Kids = Ax.Children;

Borders = Kids(1:2);

Line = Borders.XData;

You have to search the ‘Axes.Children’ result manually to find the ‘(Border)’ elements. There appears to be no way to get them automatically, or even to specifically search for a ‘Line (Border)’ or ‘Border’ entry in the ‘Kids’ variable. (There may be a way, but it would take more patience than I have tonight to find it. I’ve tried every cell and structure addressing approach I can think of or can find in the documentation, including using strcmp and related functions, and couldn’t get a good result.) It would be very nice if this was more straightforward.

Star Strider
on 14 Feb 2019

‘It seemed like missing the first border.’

The ends of a signal are not ‘peaks’ (or ‘valleys’) because there is nothing on the other sides of them to define them as such. This is the expected behaviour of findpeaks. Note that the other end of the signal is also not identified as either a ‘peak’ or a ‘valley’.

Matlaber
on 14 Feb 2019

Thanks! I am appreciate it.

Let say I want to plot the first peak (range from 1700 to 1711), it turn out to be a full range of "pks" and "locs" value.

I am not sure can I plot only specific range and then find the pks in that specific range?

load sunspot.dat

year = sunspot(:,1);

avSpots = sunspot(:,2);

findpeaks(avSpots,year,'Annotate','extents','WidthReference','halfheight')

title('Signal Peak Widths')

axis([1700 1711 0 100])

hold on

[pks,locs] = findpeaks(-avSpots,year)

plot([locs; locs], [zeros(size(pks)); -pks], '+r', 'MarkerSize',10)

hold off

Results:

pks =

0

-11.0000

-5.0000

-5.0000

-47.7000

-9.6000

-11.4000

-7.0000

-10.2000

-4.1000

-43.1000

0

-1.8000

-8.5000

-10.7000

-4.3000

-44.0000

-7.3000

-11.3000

-3.4000

-6.3000

-26.2000

-2.7000

-53.8000

-1.4000

-5.8000

-5.7000

-9.6000

-4.4000

-10.2000

-66.6000

-12.6000

-13.4000

locs =

1711

1723

1733

1744

1751

1755

1766

1775

1784

1798

1803

1810

1823

1833

1843

1856

1863

1867

1876

1878

1889

1897

1901

1906

1913

1923

1933

1944

1954

1964

1971

1976

1986

Maybe I should change the code in ploting in a specific range, but i run out of idea.

Star Strider
on 14 Feb 2019

‘I am not sure can I plot only specific range and then find the pks in that specific range?’

You can. Starting with:

[pks,locs] = findpeaks(-avSpots,year)

(or something similar) then calculate the indices as as:

idx = find((year >= yr1) & (year <= yr2));

where ‘yr1’ is the beginning year and ‘yr2’ is the end year, then analyse your data as:

spots_sub = avSpots(idx);

year_sub = year(idx);

That should work (I did not test it).

Sign in to comment.

Answer by João
on 7 Feb 2019

Try this,

[pks,locs] = findpeaks(PeakSig,x,'Annotate','extents','WidthReference','halfheight')

The variable locs have the indexes of the peaks found. Use them like this to remove a specific peak (your case the third):

PeakSig(locs(3)) = [];

Matlaber
on 8 Feb 2019

Thanks for your reply.

Can you elebrate more on the following code meaning:

PeakSig(locs(3)) = [];

Is that mean PeakSig find the points of "locs" at 3rd point?

If I want to find 1st point, it will be:

PeakSig(locs(1)) = [];

However, when I run it, it give error:

>> PeakSig(locs(3)) = []

Subscript indices must either be real positive integers or logicals.

João
on 8 Feb 2019

I didn't notice your were using x in findpeaks. You need to find the index that corresponds to locs. Do it like this then:

[pks,locs] = findpeaks(PeakSig,x,'Annotate','extents','WidthReference','halfheight')

peakToFind = 1; % the peak you want to delete (in this case the first one)

% where you get the postion in x corresponding to locs

idx_x = find(x==locs(peakToFind));

PeakSig(idx_x) = [];

Matlaber
on 9 Feb 2019

Thanks for your reply.

I managed to find the peak point, which is below:

pks =

4.8799 4.0040 3.0328 1.9994 2.2135 3.0039

locs =

0.1031 0.2002 0.2833 0.4995 0.7057 0.7998

Thus,

peakToFind = 1; % the peak you want to delete (in this case the first one)

% where you get the postion in x corresponding to locs

idx_x = find(x==locs(peakToFind));

PeakSig(idx_x)

Give the answer:

ans =

4.8765

which is the first peak answer.

However, how can I plot of first segment of the peak?

Sign in to comment.

Answer by Image Analyst
on 9 Feb 2019

The borders appear to be available in findpeaks() at line 558 (in R2018b version):

% get the x-coordinates of the half-height width borders of each peak

[wxPk,iLBh,iRBh] = getPeakWidth(yFinite,x,iPk,bPk,iLB,iRB,refW);

See it with edit, then search for border

>> edit findpeaks.m

Make a copy of findpeaks.m and call it findpeaksandborders() in some utilities folder on your path with all your other m-files. BE SURE NOT TO ALTER THE ORIGINAL ONE!!!

Then have findpeaksandborders() return the borders (iLB and iRB) in the list of output arguments.

Matlaber
on 11 Feb 2019

Thanks. I tried edit the "findpeaksandborders.m" in my matlab directory (not in matlab file under Program File) following your suggestion.

[pks,locs,Wpk,Ppk, iLB, iRB] = findpeaksandborders(PeakSig,x)

iLB;

iRB;

It said:

Error using findpeaksandborders

Too many output arguments.

Error in Find_All_Peak (line 315)

[pks,locs,Wpk,Ppk, iLB, iRB] = findpeaksandborders(PeakSig,x)

In your words "make sure you accept all 6 returned variables". Any idea which part should I check?

Thanks.

Image Analyst
on 14 Feb 2019

Looks like you got it working since you've accepted an answer.

Matlaber
on 14 Feb 2019

I used the above option. I still unable to figure out the error:

Error using findpeaksandborders

Too many output arguments.

Error in Find_All_Peak (line 315)

[pks,locs,Wpk,Ppk, iLB, iRB] = findpeaksandborders(PeakSig,x)

However, it cannot find the first border.

I think it is due to invert of peak.

load sunspot.dat

year = sunspot(:,1);

avSpots = sunspot(:,2);

findpeaks(avSpots,year,'Annotate','extents','WidthReference','halfheight')

title('Signal Peak Widths')

hold on

[pks,locs] = findpeaks(-avSpots,year)

plot([locs; locs], [zeros(size(pks)); -pks], '+r', 'MarkerSize',10)

hold off

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.