Segmenting sinusoidal time-series data

I have some data that was collected by a mobile phone's gyroscope sensors. I would like to be able to chunk out one "repetition" of the motion. An example of a sample run is shown here (apparently the MathWorks image upload didn't work right): http://i.imgur.com/GuEgK2y.png
I would like to be able to determine how long a period is, and where they start (doesn't matter if the starting point is max or min amplitude or a center amplitude). I tried using xcorr, which resulted in a plot with some waves centered around 50, whereas manual inspection of the data shows a period of about 2000 between the first two peaks. What should I be looking into to figure out how to do this?

 Risposta accettata

Without your actual data, I can only guess at an approach. I would begin by detrending it (I used polyfit and polyval, there are several options), then use circshift to identify the zero-crossings, and from them the periods and frequencies:
t = 0:1.3E+4;
s = 60 + 5*exp(-5*t/1.3E+4) + sin(2*pi*t/3000); % Create Data
figure(1)
plot(t, s); % Original Data
p = polyfit(t, s, 3);
sd = s - polyval(p, t); % Detrend
xci = find(sd.*circshift(sd, [0 -1]) <= 0);
xci = xci(1:end-1); % Find Inices Of Zero-Crossings
figure(2)
plot(t, sd)
hold on
plot(t(xci), sd(xci), '+r')
hold off

4 Commenti

Hmm. When I plot sd vs t (using my data), I see that the data has been adjusted as expected and has zero-crossings, but xci is an empty array.
Could you explain a little more what you're doing with find and circshift? I don't understand why you're shifting the array.
If ‘xci’ is empty, that means your data are a column rather than a row vector. (This is the problem of not having your original data to work with.) The first approach is to switch the argument vector in the circshift call:
xci = find(sd.*circshift(sd, [-1 0]) <= 0);
Try it now.
The circshift call shifts the vector (in this instance, see the documentation for details) one position to the left (or up) (-1), then multiplies it by the unshifted vector. This creates negative values only where zero-crossings occur. The find call then locates the indices of them. It is possible to extend this to include a loop with an interp1 call at each iteration (for coarsely-sampled data) to get more accurate zero-crossing estimates. I kept it simple here.
Ok, switching which dimension was shifted worked, thank you.
My pleasure.

Accedi per commentare.

Più risposte (0)

Categorie

Prodotti

Community Treasure Hunt

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

Start Hunting!

Translated by