Matlab is particularly nice for dealing with quantitative data. I decided to dive deeper into the tool by coding up a graphing application for my treadmill workouts recorded using the Nike+ application that samples data from the built-in accelerometer of the iPod Nano.
This is not necessarily functionality that I'm currently missing; normally I use Excel or the Nike+ website (based on Adobe Flash). Perhaps Matlab is overkill, but there's something deeply satisfying about smoothing the accelerometer data using just one function call like:
c = smooth(b);
where b and c are vectors. The default is a simple moving average (span 5). But because it's Matlab, you can play with many different smoothing options:
I'm looking to produce a graph like this automatically:
We have three graphs overlaid on top of one another; I'm plotting speed against time:
- the raw data (in gray),
- the smoothed data (in thick red), and
- the treadmill speed setting (in blue)
When the iPod Nano is attached to my Mac, the raw xml file for my workout looks something like this:
The Nano records a datapoint, the cumulative distance in km, every 10 seconds.
We can grab those raw distances between the <extendedData dataType="distance"> and </extendedData> tags using a simple 3 line Perl program, as Matlab is perhaps not the best tool for this job:
The cool thing though is that Matlab can call Perl to stick the distances in a file (distances.txt):
perl('getdistances.perl',f)
Then we can call the importdata function to read those distances into an array (a):
a = importdata('distances.txt');
To extract the speeds in km/h units, we do a little conversion from our raw cumulative distances in km/10 sec units. It's a shame that the MuPad (symbolic math) part of Matlab is not well-integrated with Matlab proper because the unit::convert system there is cool. For example, you can define your own units like km/10 sec. (Anyway, I couldn't figure out how to make MuPad and Matlab work together.) Fortunately, the function convvel (convert velocity) can do km/s to km/h.
Finally, the rest is just plotting the data points. Setting a few labels and the ticks on the graph. I packaged this whole sequence up in a function called nike and saved it in Documents/Matlab/nike.m:
To use the graphing, I just call the function nike with the xml filename recorded by the iPod. (Matlab knows to look for this function in Documents/Matlab by default.) The call to nike (see below) returns the number of data points (181).
And up pops this graph:
This only works well when I have Matlab already open. For some reason, on my Macbook Pro, Matlab takes forever to start up.
There is a second call above to a function called treadmill, which handles the overlay of my treadmill program onto the iPod data.
I supply a vector [7,15,7.5,5,7,5,7.5,5] describing my workout: this means first 7 mph for 15 mins, followed by 7.5 mph for 5 mins, followed by 7 mph for 5 mins, and finally, 7.5 mph for 5 mins, for a total of 30 minutes. Note this is America, so the treadmill is in mph and I use convvel again to flip the values to km/h. Function implementing this is stored in Documents/Matlab/treadmill.m:
And I get my overlay:
Now, what's also cool about Matlab is that it's both interactive and programmatic. So, after running those two functions, I can simply click on the y-axis and zoom into where I want, resize the graph, add a few more labels, and put up a legend. The result:
So nice and easy.
Actually, the Adobe Flash-based graph from the Nike+ website is not bad either (although we can't have overlays):
No comments:
Post a Comment