sphear_findpeaks.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. %% -*- mode: octave -*-
  2. %%
  3. %% https://ccrma.stanford.edu/~jos/sasp/Matlab_listing_findpeaks_m.html
  4. %%
  5. %% FINDPEAKS Find up to npeaks interpolated peaks in data.
  6. %%
  7. %% [peakamps,peaklocs,peakwidths,resid] =
  8. %% findpeaks(data,npeaks,minwidth,maxwidth,minpeak,debug);
  9. %%
  10. %% finds up to npeaks interpolated peaks in real data.
  11. %% A peak is rejected if its width is
  12. %% less than minwidth samples wide(default=1), or
  13. %% less than minpeak in magnitude (default=min(data)).
  14. %% Quadratic interpolation is used for peak interpolation.
  15. %% Left-over data with peaks removed is returned in resid.
  16. %% Peaks are returned in order of decreasing amplitude.
  17. %% They can be sorted in order of location as follows:
  18. %% [peaklocs,sorter] = sort(peaklocs);
  19. %% amps = zeros(size(peakamps));
  20. %% npeaks = length(peaklocs);
  21. %% for col=1:npeaks,
  22. %% amps(:,col) = peakamps(:,sorter(col));
  23. %% end;
  24. %% They can be sorted in order of width as follows:
  25. %% [peakwidths,sorter] = sort(peakwidths);
  26. %% peakamps = peakamps(sorter);
  27. %% peaklocs = peaklocs(sorter);
  28. function [peakamps,peaklocs,peakwidths,resid] = ...
  29. sphear_findpeaks(data,npeaks,minwidth,maxwidth,minpeak,debug);
  30. len = length(data);
  31. if nargin<6,
  32. debug = 0;
  33. end;
  34. if nargin<5,
  35. minpeak = min(data);
  36. end;
  37. if nargin<4,
  38. maxwidth = 0;
  39. end;
  40. if nargin<3,
  41. minwidth = 1;
  42. end;
  43. if nargin<2,
  44. npeaks = len;
  45. end;
  46. peakamps = zeros(1,npeaks);
  47. peaklocs = zeros(1,npeaks);
  48. peakwidths = zeros(1,npeaks);
  49. if debug, peaksarr = 1.1*max(data)*ones(size(data)); end;
  50. if debug, orgdata = data; end;
  51. if debug, npeaks, end
  52. nrej = 0;
  53. pdebug=debug;
  54. ipeak=0;
  55. while ipeak<npeaks
  56. [ploc, pamp, pcurv] = sphear_maxr(data);
  57. if (pamp==minpeak), warning('findpeaks:min amp reached');
  58. break;
  59. end
  60. plocq = round(ploc);
  61. ulim = min(len,plocq+1);
  62. camp = pamp;
  63. %%
  64. %% Follow peak down to determine its width
  65. %%
  66. drange = max(data) - minpeak; % data dynamic range
  67. tol = drange * 0.01;
  68. dmin = camp;
  69. while ((ulim<len) && (data(ulim)<=dmin+tol)),
  70. camp = data(ulim);
  71. ulim = ulim + 1;
  72. if (camp<dmin), dmin=camp; end
  73. end;
  74. ulim = ulim - 1;
  75. lamp = camp;
  76. llim = max(1,plocq-1);
  77. camp = pamp;
  78. dmin = camp;
  79. while ((llim>1) && (data(llim)<=dmin+tol)),
  80. camp = data(llim);
  81. llim = llim - 1;
  82. if (camp<dmin), dmin=camp; end
  83. end;
  84. llim = llim + 1;
  85. uamp = camp;
  86. %%
  87. %% Remove the peak
  88. %%
  89. data(llim:ulim) = min(lamp,uamp) * ones(1,ulim-llim+1);
  90. %%
  91. %% Reject peaks which are too narrow (indicated by zero loc and amp)
  92. %%
  93. pwid = ulim - llim + 1;
  94. if ~(pwid < minwidth),
  95. ipeak = ipeak + 1;
  96. peaklocs(ipeak) = ploc;
  97. peakamps(ipeak) = pamp;
  98. peakwidths(ipeak) = - 1/pcurv;
  99. nrej = 0;
  100. if pdebug>1
  101. peaksarr(plocq) = pamp;
  102. maxloc = min(len,2*round(max(peaklocs)));
  103. ttl = sprintf('Peak %d = %0.2f at %0.2f, width %d',ipeak,pamp,ploc,pwid);
  104. if x == -1
  105. pdebug = 0;
  106. end
  107. end
  108. else
  109. nrej = nrej + 1;
  110. if (nrej >= 10),
  111. warning('*** findpeaks: giving up (10 rejected peaks in a row)');
  112. break;
  113. end;
  114. end;
  115. end;
  116. if (ipeak<npeaks),
  117. warning(sprintf('*** peaks.m: only %d peaks found instead of %d',ipeak,npeaks));
  118. peakamps = peakamps(1:ipeak);
  119. peaklocs = peaklocs(1:ipeak);
  120. peakwidths = peakwidths(1:ipeak);
  121. end;
  122. resid = data;
  123. end