Determine the indice of real maximum using accumarray function
I’m doing signal analysis on the peaks and valleys of a sinusoidal signal. Using accumarray has been quite effective at determining the extrema, but I’m seriously struggling with what should be a simple part of my implementation. Currently the returned peakLoc values are not integer timesteps, but a decimal average of all the timesteps that are considered part of the peak. The only new functionality I need is to get the real integer timestep for the highest (or lowest) extrema. Whether there is an option for the single accumarray line with @mean or another way, I don’t care. Over the past three days I have been slopping together different nested loops to try to pin down the behavior I want and I’m sure there’s got to be a simple way to accomplish this.
I’m sure there’s a lot of other ways I could improve this code, but I just need it working. I’m not experienced and constantly bang my head against indexing problems (whether mixing up dimension, logical indexing oddities, etc.) and other beginner problems.
function [peakLoc, peakVal] = getExtrema(durThreshold, PEThreshold, gettingMax, PEAverage, timestep)
% Gets passed duration (# of consecutive timesteps above zero) and PE threshold (0).
% Returns the timestep and PE value for all of Maximum or of Minimum extrema.
if gettingMax == true
isPeak = PEAverage > PEThreshold;
else
isPeak = PEAverage < PEThreshold;
end
CC = bwconncomp(isPeak);
peakID = labelmatrix(CC);
peakLabel = unique(peakID);
peakSize = accumarray(peakID(:)+1,1);
peakSize(1) = 0; % set the # of <0 elements to 0
realPeakLabels = peakLabel(peakSize >= durThreshold);
isRealPeak = ismember(peakID,realPeakLabels);
% Now find the max in the real peaks (realPeakLabels?), accumarray will help
peakID(~isRealPeak) = 0;
if gettingMax == true
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@max,NaN);
else
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@min,NaN);
end
%% Get the right peakLoc, not the @mean
% @mean is approximation of the timestep where the real peak value occurs
peakLoc = accumarray(peakID(:)+1,timestep(:),[numel(peakSize) 1],@mean,NaN);
peakLoc = zeros(length(peakLabel),1);
j = 1;
for i = timestep
% Get the right index
if peakID(i) > j
j = peakID(i);
end
if ismember(j, realPeakLabels)
if gettingMax == true
if PEAverage(i) > peakVal(j)
peakLoc(j) = timestep(i);
end
else
if PEAverage(i) < peakVal(j)
peakLoc(j) = timestep(i);
end
end
end
end
peakVal(1) = NaN;
peakLoc(peakLoc == 0) = NaN;
endI’m doing signal analysis on the peaks and valleys of a sinusoidal signal. Using accumarray has been quite effective at determining the extrema, but I’m seriously struggling with what should be a simple part of my implementation. Currently the returned peakLoc values are not integer timesteps, but a decimal average of all the timesteps that are considered part of the peak. The only new functionality I need is to get the real integer timestep for the highest (or lowest) extrema. Whether there is an option for the single accumarray line with @mean or another way, I don’t care. Over the past three days I have been slopping together different nested loops to try to pin down the behavior I want and I’m sure there’s got to be a simple way to accomplish this.
I’m sure there’s a lot of other ways I could improve this code, but I just need it working. I’m not experienced and constantly bang my head against indexing problems (whether mixing up dimension, logical indexing oddities, etc.) and other beginner problems.
function [peakLoc, peakVal] = getExtrema(durThreshold, PEThreshold, gettingMax, PEAverage, timestep)
% Gets passed duration (# of consecutive timesteps above zero) and PE threshold (0).
% Returns the timestep and PE value for all of Maximum or of Minimum extrema.
if gettingMax == true
isPeak = PEAverage > PEThreshold;
else
isPeak = PEAverage < PEThreshold;
end
CC = bwconncomp(isPeak);
peakID = labelmatrix(CC);
peakLabel = unique(peakID);
peakSize = accumarray(peakID(:)+1,1);
peakSize(1) = 0; % set the # of <0 elements to 0
realPeakLabels = peakLabel(peakSize >= durThreshold);
isRealPeak = ismember(peakID,realPeakLabels);
% Now find the max in the real peaks (realPeakLabels?), accumarray will help
peakID(~isRealPeak) = 0;
if gettingMax == true
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@max,NaN);
else
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@min,NaN);
end
%% Get the right peakLoc, not the @mean
% @mean is approximation of the timestep where the real peak value occurs
peakLoc = accumarray(peakID(:)+1,timestep(:),[numel(peakSize) 1],@mean,NaN);
peakLoc = zeros(length(peakLabel),1);
j = 1;
for i = timestep
% Get the right index
if peakID(i) > j
j = peakID(i);
end
if ismember(j, realPeakLabels)
if gettingMax == true
if PEAverage(i) > peakVal(j)
peakLoc(j) = timestep(i);
end
else
if PEAverage(i) < peakVal(j)
peakLoc(j) = timestep(i);
end
end
end
end
peakVal(1) = NaN;
peakLoc(peakLoc == 0) = NaN;
end I’m doing signal analysis on the peaks and valleys of a sinusoidal signal. Using accumarray has been quite effective at determining the extrema, but I’m seriously struggling with what should be a simple part of my implementation. Currently the returned peakLoc values are not integer timesteps, but a decimal average of all the timesteps that are considered part of the peak. The only new functionality I need is to get the real integer timestep for the highest (or lowest) extrema. Whether there is an option for the single accumarray line with @mean or another way, I don’t care. Over the past three days I have been slopping together different nested loops to try to pin down the behavior I want and I’m sure there’s got to be a simple way to accomplish this.
I’m sure there’s a lot of other ways I could improve this code, but I just need it working. I’m not experienced and constantly bang my head against indexing problems (whether mixing up dimension, logical indexing oddities, etc.) and other beginner problems.
function [peakLoc, peakVal] = getExtrema(durThreshold, PEThreshold, gettingMax, PEAverage, timestep)
% Gets passed duration (# of consecutive timesteps above zero) and PE threshold (0).
% Returns the timestep and PE value for all of Maximum or of Minimum extrema.
if gettingMax == true
isPeak = PEAverage > PEThreshold;
else
isPeak = PEAverage < PEThreshold;
end
CC = bwconncomp(isPeak);
peakID = labelmatrix(CC);
peakLabel = unique(peakID);
peakSize = accumarray(peakID(:)+1,1);
peakSize(1) = 0; % set the # of <0 elements to 0
realPeakLabels = peakLabel(peakSize >= durThreshold);
isRealPeak = ismember(peakID,realPeakLabels);
% Now find the max in the real peaks (realPeakLabels?), accumarray will help
peakID(~isRealPeak) = 0;
if gettingMax == true
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@max,NaN);
else
peakVal = accumarray(peakID(:)+1,PEAverage(:),[numel(peakSize) 1],@min,NaN);
end
%% Get the right peakLoc, not the @mean
% @mean is approximation of the timestep where the real peak value occurs
peakLoc = accumarray(peakID(:)+1,timestep(:),[numel(peakSize) 1],@mean,NaN);
peakLoc = zeros(length(peakLabel),1);
j = 1;
for i = timestep
% Get the right index
if peakID(i) > j
j = peakID(i);
end
if ismember(j, realPeakLabels)
if gettingMax == true
if PEAverage(i) > peakVal(j)
peakLoc(j) = timestep(i);
end
else
if PEAverage(i) < peakVal(j)
peakLoc(j) = timestep(i);
end
end
end
end
peakVal(1) = NaN;
peakLoc(peakLoc == 0) = NaN;
end signal processing MATLAB Answers — New Questions