# Extracting data from a signal

25 views (last 30 days)

Show older comments

##### 2 Comments

Adam Danz
on 9 Mar 2020

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.

### Accepted Answer

Adam Danz
on 9 Mar 2020

Edited: Adam Danz
on 10 Mar 2020

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 Comments

Adam Danz
on 10 Mar 2020

Edited: Adam Danz
on 10 Mar 2020

### More Answers (1)

Hank
on 9 Mar 2020

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 Comments

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!