MATLAB: Extracting data from a signal

signal processing

my signal is a single column vector (I have attached an image how the signal looks like), I want to extract data from this vector from whenever the signal starts rising until it reaches the peak for each iteration and saving corresponding data from each iteration in a new separate column vector. Any suggestions?

Best Answer

This segments the monotonically increasing part of each pulse, as depicted in the 2nd image in my comment under your question. See inline comments for details.
Input: signal (provided by your mat file)
Output: startIdx (the starting index of each rise), locs (the index of the peaks).
Method 1
This method is not recommended; see method 2 below.
% Get coordinates of peaks

% The first line below is another option
% [~, locs] = findpeaks(signal, 'MinPeakHeight', range(signal)*.4 + min(signal), 'MinPeakDistance', 200);
signalSmooth = smooth(signal,20);
[~, locs] = findpeaks(signalSmooth, 'MinPeakHeight', range(signal)*.4 + min(signal), 'MinPeakDistance', 200);
% Look for 4 consecutive increases
mm = movmean([inf;diff(signal)] > 0, [0,3]) == 1;
mmIdx = find(mm);
firstOnes = find([mm(1);diff(mmIdx)>1]);
startIdx = mmIdx(firstOnes);
clf()
plot(signal, 'b-')
hold on
plot(locs, signal(locs), 'r*')
plot(startIdx, signal(startIdx), 'mx', 'LineWidth',2)
% Now exact the segments and plot them separately
% Extract


segements = arrayfun(@(start,stop){signal(start:stop)},startIdx,locs);
figure()
hold on
cellfun(@(c)plot(c),segements)
Or, if you want to preserve the x-values,
% Extract
segements = arrayfun(@(start,stop){signal(start:stop)},startIdx,locs);
segement_xvalues = arrayfun(@(start,stop){start:stop},startIdx,locs);
figure()
hold on
cellfun(@(x,y)plot(x,y),segement_xvalues, segements)
Update: Method 2
New smoothing method; a new, more robust, method of finding the start of each rising segment that ends at a peak.
load('signal3.mat');
signal = s3;
% Get coordinates of peaks
signalSmooth = smoothdata(signal,'gaussian', 20);
% NOTE: You may have to play around with findpeak() options to optimize
% this to your data! See the documentation.
[~, locs] = findpeaks(signalSmooth, 'MinPeakHeight', range(signal)*.1 + min(signal), 'MinPeakDistance', 200);
% Determine which points are increasing releative to previous point
isIncrease = diff([inf; signalSmooth]) > 0 ;
notIncrIdx = find(~isIncrease);
% For each peak, find the closest previous point that isn't increasing.
idx = notIncrIdx(:) < locs(:).';
startIdx = arrayfun(@(col)find(idx(:,col),1,'last'),1:numel(locs));
startIdx = notIncrIdx(startIdx)+1;
clf()
plot(signal, 'b-')
hold on
% plot(signalSmooth, 'c-')
plot(locs, signal(locs), 'r*')
plot(startIdx, signal(startIdx), 'mx', 'LineWidth',2)
% Extract
segements = arrayfun(@(start,stop){signal(start:stop)},startIdx,locs);
segement_xvalues = arrayfun(@(start,stop){start:stop},startIdx,locs);
figure()
hold on
cellfun(@(x,y)plot(x,y),segement_xvalues, segements)