Monthly Archives: December 2015

Nordic Track 2450 Treadmill

We recently got a Nordic Track 2450 treadmill to help us stay fit through the long, dark, cold, wet Seattle winters. I have been running on the commercial treadmills (Precor 932i) at the gym for the past few years, so that’s my point of comparison.

Good Stuff

We ordered it online because none of the local shops could come close to the price. It has a good warranty, 30 day no hassle return, shipping delivered to the room of our choice (which is important as it weighs over 300 lbs.), shipped promptly and arrived in perfect condition. Unpacking and assembly took nearly 2 hours but was simple.

The Nordic Track feels as solid and smooth as the more expensive Precor, has a more powerful motor, a slightly bigger running deck (60″ x 22″), elevation from -3* to +15*, adjustable deck firmness, and far more features. The iFit capabilities are super-cool and work well, even supporting multiple users under the same account.

It has 3 fans to blow air on you, cooling and reducing the amount of raw sweat dripping off your body onto the machine. The fans work well enough and aren’t too loud. They can be set manually or automatically, where they blow harder when you run faster. I find the auto mode doesn’t blow hard enough – during a tough workout when my heart rate is the in 160-170 range, I need those fans on full bore.

It includes a wireless heart rate chest strap that works well. The system is polar compatible. It also has handles you can grab that read your heart rate. When first grabbing the handles, I get crazy readings, often half or twice my actual heart rate, for the first minute or so, before it stabilizes on the correct reading. The chest strap doesn’t do this – it reads accurately from the start.

If none of the 40 built-in workouts float your boat, you can create your own – any number of your own – customizing elevation, speed, etc. You can also schedule them, set goals and track progress toward goals, if you want. However, all this requires iFit.

iFit adds a lot of capability and fun to this treadmill. You can download any number of workouts of all types and difficulty levels, many with Google street view maps across the world, including some exotic locations, and you can design your own too. When you run these, you see the actual street view and the elevation changes to match the terrain. It moves along slowly, more like a slide show than a video, but it’s still neat. I was a bit concerned about iFit since my research showed it had a rocky launch with lots of bugs a couple of years ago. They’ve fixed most of that, it works pretty well but still has the occasional crash – more on that below.

The control console response is not instantaneous, but reasonably quick, the touch screen responds to light touch and doesn’t miss gestures like swipes. The screens are well organized intuitively, easy to navigate.

Bad Stuff

iFit is marked as optional, yet it’s required to get the most of this machine. And it costs $100 / year. Without iFit, you can run the machine manually and it has 40 different built-in workouts. But I couldn’t find the simple workout I wanted: intervals with 2 minutes slow and 1 minute fast. I call this a simple 2-1 interval. In fact, among all 40 workouts there were no simple intervals at all! Not 1-1, 2-1, 3-1 or anything close to that. So the “40 built-in workouts” is just a marketing ploy – it’s true, but misleading and not useful. As mentioned above, you can build your own workouts, but only with iFit.

The console runs Android and I can tell from the boot screen it’s some ancient 2.X version. It has a built-in browser that is so terrible as to be unusable. On some sites (including, inexplicably, iFit itself), no text appears, making it unusable. Perhaps it’s a character set or font issue? I don’t know, but you might as well disable the browser in the machine settings because it’s totally unusable. Other than this, the console works just fine.

The heart rate monitor bar is effectively unusable. It’s wildly inaccurate (at least for me) and using it can crash the console under certain conditions (see below). If you want heart rate, use the wireless chest strap – it’s more accurate and it doesn’t crash the console.

The most annoying problem with the 2450 is the console occasionally crashes, sometimes while in the middle of a workout. Here are some conditions that trigger this:

  • Using the heart rate monitor bar while running a Geo workout in street view. This will usually crash the console, though it doesn’t happen immediately.
    • Workaround: don’t do this. If you want heart rate, use the wireless chest strap – it’s more accurate anyway. Or, if you’re running a Geo workout, switch to map or satellite view before using the heart rate monitor bar.
  • If you have an un-named workout in your history, the 2450 console will crash when you touch the yellow “log-history” button.
    • Workaround: use the iFit website to rename or remove the offending workout.

Conclusion

I think the 2450 is a good value. It has some quirks but they have workarounds. I was pleasantly surprised to find it as solid, smooth and quiet as more expensive commercial treadmills, and total cost shipped to my door was about $2,100. The iFit subscription is required for all practical purposes, though at $100 / year, supporting up to 4 individuals, each with their own history, workouts, etc. the cost of an iFit subscription is small in comparison.

Take that Data with a Grain of Salt

I wanted to geographically visualize Twitter activity by zip code. I had a set of Tweets captured from GNIP Powertrack. Each tweet has the author’s public profile, as well as the tweet text and several other fields.

First, I got the zip code data: about 42,500 zip codes each with lat/lon coordinates and population estimate from US 2010 Census. Next, I loaded it into a Hive table. I used Hive because the tweet data was big enough to live in Hadoop, though you could do the geo zip code manipulation I’m describing in any database.

Next, from the Twitter data I found the closest zip code to each author by computing the distance from the author’s lat/lon to the lat/lon of every zip code. Of course, this only works for people who put their location in their Twitter public profile, but that was surprisingly many people. I only needed the closest, which simplified the computation since units didn’t matter.

Next, I computed metrics (like tweet counts) per zip code. Raw numbers would not be useful – of course most of the tweets come from the zips with the most people. I divided by zip code population to get per-capita values.

At this point I should have been done, in which case it would be so simple and quick there would be no reason to write about it here. However, that’s not what happened. These values were all over the map: spanning 5 orders of magnitude (0 – 10^5). Per capita?! This didn’t make sense. I expected values of zero or close to zero, but reasonable maximums would be a fraction of 1 – nowhere near the tens of thousands.

Investigation revealed the outliers were tiny zip codes like 30334 covering about 1 square block having tiny populations like 1. Whenever a prolific tweeter (or tweet-bot) resides in one of these it blows out the data. Clearly, these are zip codes too new to have accurate 2010 Census data.

The problem is actually more general: any small zip code can blow out the data – even if its population data is accurate. I needed a way to factor out these tiny zip codes. One way to do this is to merge each small zip code into its nearest big zip code. Split zip codes into 2 groups: small and big, using a threshold population. I made a histogram of zip codes by population to see what would be a good split value. I chose 25-75 since 25% is about 10,000 zip codes, which is enough for smooth dense coverage. The histogram showed a population of about 8,000 would give this 25-75 split.

Next, I found the nearest big zip for each small zip. In SQL this is a full outer join between the big and small zip sets, computing distance between each, then picking min(distance) for each small zip. With roughly 10,000 big zips and 30,000 small zips, the cross product would have about 300 MM rows.

Now for a brief aside on Spark-SQL versus Hive. In most of my work, Spark-SQL is about 10x faster than Hive. Yet when I ran this join, Spark-SQL was going to take 18+ hours! I copied the data to Hadoop and ran it in Hive, and it took 30 minutes. So it appears Spark-SQL is still new enough they have some work to do optimizing certain kinds of joins.

Now, SQL makes it hard to select which big zip the minimum distance came from. That is, you can select zip_small, min(distance) and group by zip_small. But it doesn’t tell you which big zip that minimum came from. Once you know that minimum distance, you can select the small zip and distance from the above cross-product table, but this won’t necessarily be unique. Each small zip has about 10,000 big zips, and it might be the exact same distance from several.
this duplication explodes the join.

The textbook workaround would be to rank and select by rank within distance, but that would be complex. Instead, I thought of a simple hack: force all the distances to be unique, so you can select the small zip and min distance from the cross-product table without any duplicates exploding your join.

To make the distances unique, sprinkle some random bits into them, and do it in the least significant bits so it doesn’t affect which is closest. Put differently, salt the distances with just enough salt to ensure they’re unique, and push the salt down into the least significant bits so it doesn’t affect comparisons.

Doing this is simple. First, query to find how close together are the closest distances. In my case it was about 0.1 (unitless measure). Then, generate a random float between 0 and 1, multiply it by 1/10 of that figure to be safe, and add it to each computed distance. Because computers generate random numbers in sequences, getting a duplicate is statistically improbable, so every distance will be unique, and you scaled it small enough (in my case by multiplying by 0.01) it won’t change each zip’s closest neighbor.

Next, for each big zip, sum the populations of all its small neighbors and add this sum to the big zip’s population to get the population of the big zip with all its neighboring small zips.

Now we have a table that has: zip_small, zip_big, pop_sum. Map each tweet’s author’s zip to zip_small, then report it as zip_big and divide by zip_sum to get per capita.

Of course, we need to add big zips to this table too, so each big zip maps to itself with the population sum.

This worked beautifully and smoothed the data.

NOTE: there are many applications where adding a little random noise is helpful. This is just one example, and a simple one.

Stop that Pesky Authorization Dialog

Some people, including me, have seen a dialog pop up on Ubuntu 15.10 asking for password authorization to “change own user data”. This is annoying and should not happen. The blunt force solution is suggested here. The problem with this solution is you won’t be able to do anything in the desktop GUI that actually does require root, because it kills process that prompts for the password. A real solution is needed.

Here’s a real solution that worked for me:

Go to the directory /etc/polkit-1/localauthority/50-local.d

Create a file called org.freedesktop.accounts.change-own-user-data.pkla, like this:

-rw-r–r– 1 root root 202 DecĀ  7 19:40 /etc/polkit-1/localauthority/50-local.d/org.freedesktop.accounts.change-own-user-data.pkla

File Contents:

[Do not prompt users with “Authentication is required to change your own user data” messages]
Identity=unix-user:*
Action=org.freedesktop.accounts.change-own-user-data
ResultAny=yes
ResultInactive=yes

That’s it – you’re done!