Extracting data from a signal
조회 수: 24 (최근 30일)
이전 댓글 표시
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?
댓글 수: 2
Adam Danz
2020년 3월 9일
Which one of these images (if any) indicate when the signal starts to rise?
In the first image, there are many tiny spike where the signal technically isn't monotonically rising.
채택된 답변
Adam Danz
2020년 3월 9일
편집: Adam Danz
2020년 3월 10일
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)
댓글 수: 6
Adam Danz
2020년 3월 10일
편집: Adam Danz
2020년 3월 10일
When I zoom into a portion of the plot, the magenta x marks look reasonable. The flat lines at the beginning of your M2.png figure are due to the similar y-values clustered around the beginning of each segment. You can see this below. If that's a problem, you could offset the startIdx by a few values.
추가 답변 (1개)
Hank
2020년 3월 9일
Adam, I think the crosshairs in the first image are where the derivative becomes positive: the signal starts to rise. I would use this fact to cut the data programatically. First smooth the data and then take the derivative. The continguous regions where the derivative is positive are the regions you're looking for.
sig = load('signal'); % load
sig = sig(:); % column vector
sigsmooth = smooth(sig,100); % boxcar 100 smoothing
dsig = [0; diff(sig)]; % derivative, padded with 0 so the length doesn't change.
dsigrising = dsig>0; % this vector is true in the regions you want data.
Clustering the rising regions is not something I know how to do programatically, but maybe this could make the boundaries distinct enought that you could do it by hand.
댓글 수: 0
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!