3

This is a little complicated to explain. I have time series data formatted like this: https://docs.google.com/spreadsheets/d/1B8mN0uD-t4kQr2U20gS713ZFHN6IgGB7OMR3-pqJjrw/edit?usp=sharing

That data represents voltage recordings at .01s intervals. When plotted it looks like this:

http://i.imgur.com/yatlBLt.jpg .

Essentially what I want to do is find the time at which the first peak in each very narrow pair occur (ie at ~.1, .75, 1.6, etc).

The time values are in a separate array, but the index values (row numbers) correspond between the two sets.

Any ideas on how to do this?

My initial attempt was something like this from the matlab manual

function [edges2] = risingEdge2(time, data)
threshold = 0.4;
offsetData = [data(2:end); NaN];
edges2 = find(data < threshold & offsetData > threshold);
end

I couldn't figure out a good way to ignore for n seconds after the first peak...I'm also getting many more peaks than expected...probably because of noisy data.

user3746901
  • 73
  • 1
  • 5
  • 1
    Is there something that you have tried but are having trouble with? – AnonSubmitter85 Nov 07 '14 at 14:29
  • can you use the signal processing toolbox? – Benoit_11 Nov 07 '14 at 14:34
  • @AnonSubmitter85 just updated with my attempt – user3746901 Nov 07 '14 at 14:43
  • Well, there's the `findpeaks` command in the sig proc toolbox, but I don't know if that will work here with the up-down nature on the top of the train of square pulses. How general and robust does this have to be? If you're happy with the simple thresholding, then you could just threshold and ignore regions that are above the threshold for more than N seconds. It's kind of a hack to do it that way though. If the narrow signals are periodic, could you isolate them in the frequency domain? Again, the train of square pulses might make that hard to do. – AnonSubmitter85 Nov 07 '14 at 15:02
  • @AnonSubmitter85 so the data are pretty consistent in that there will always be 5 of these narrow peaks I want to grab and that they will be the same magnitude. It's a really specific application, so it just has to work on these data, which again, are almost entirely identical. The only thing that changes between sets is the spacing between the 5 cycles. – user3746901 Nov 07 '14 at 15:10
  • 1
    So if you just threshold, you'll get a vector of ones and zeros. Find the lengths of each contiguous span of 1's and discard those that are too long. What's left will be the narrower impulses. – AnonSubmitter85 Nov 07 '14 at 15:12

2 Answers2

0

The following approach seems to work for the given data.

%// Define parameters
window_size = 200;
stepsize = 0.4; %// to be used for quantizing data into three levels - 0, 0.4, 0.8

%// Perform a sliding max to get rid of the dips within the spikes
slmax_data = nlfilter(data,[window_size 1],@max);

enter image description here

%// Quantize sliding max data to three levels as the plot seem to suggest
quantized_slmax_data = round((slmax_data-min(slmax_data))./stepsize);

enter image description here

If you zoom into the above figure, you will see ledges around the high peaks -

enter image description here

%// Get sliding mode to get rid of the short ledges around the high peaks
slmax_mode_data = nlfilter(quantized_slmax_data,[window_size 1],@mode);

enter image description here

%// Finally, find the indices where the mode data jump from 0 to 1 only, which
%// correspond to the start of spikes
index = find(diff(slmax_mode_data)==1)+window_size/2;

Output -

index =
         682
        8048
       16487
       24164
       31797
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Oh I like this solution. I can't get it to work though. I'm unfamiliar with nlfilter...I keep getting the error Undefined function 'nlfilter' for input arguments of type 'function_handle'. EDIT: I think I need to install image processing toolbox. – user3746901 Nov 08 '14 at 04:25
  • @user3746901 Yeah Image Proc. Toolbox would be needed to use these codes! Let me know how it goes? – Divakar Nov 08 '14 at 05:38
0

Here -- find all rising edges, then find those that are very close together and take the first.

rising_edges = find(diff(data > .3) > 0);
first_of_paired_edges = find(diff(time(rising_edges)) < 500);

first_rising_edge_times = time(rising_edges(first_of_paired_edges));

You could then slide up the edge to the peak.

first_peak_times = time(arrayfun( @(n) n+find(diff(data(n+[0:1000]) < 0, 1, 'first'), 
                        rising_edges(first_of_paired_edges));
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720