A month ago I was hiking in the Fossil Ridge Wilderness Area. I wore several sensors over the four days — unfortunately, I lost the Fitbit and the Q-Sensor had a clock error which corrupted its data. Disappointing, but I did have two Garmin devices that held up, recording position and heartrate.

I finally managed to create a map from the data. I suppose I could have done this more efficiently with Google Earth, but I decided to parse the GPX files and draw my own paths with python, overlaying the result on a Google terrain map, which looks a lot nicer. The brighter red the path, the higher my heartrate — however, Im not sure that this ended up revealing anything particularly compelling. It is just, a la Certeau, a curious relic that substitutes for a rich experience.

Regardless, making it was a good exercise. Two complementary pieces of code were essential when doing this kind of thing outside of a mapping platform. First, when finding the geographic distance between two latitude/longitude pairs, Euclidean distance doesnt work, as we’re operating on an elliptical sphere. For that, there is the haversine formula:

def geo_distance(pt0, pt1, miles=True):
    ”“” Convert the distance between two points, specified (lon, lat), \
        to miles (or kilometers)
    ”“”
    LON, LAT = 0, 1
    pt0 = math.radians(pt0[LON]), math.radians(pt0[LAT])
    pt1 = math.radians(pt1[LON]), math.radians(pt1[LAT])
    lon_delta = pt1[LON] - pt0[LON]
    lat_delta = pt1[LAT] - pt0[LAT]
    a = math.sin(lat_delta / 2)**2 + math.cos(pt0[LAT]) * math.cos(pt1[LAT]) * math.sin(lon_delta / 2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = 6371 * c # radius of Earth in km
    if miles:
        d *= 0.621371192
    return d

Secondly, in order to plot data on a two-dimensional plane and have it line up with an image from Google, I needed to use the formula for the Mercator projection. This one is compliments of OpenStreetMap. It gives you coordinates relative to the globe, which have to be further scaled.

def geo_project(pt):
    ”“” Project a (lon, lat) point to x,y space using
        the Mercator projection
        http://wiki.openstreetmap.org/wiki/Mercator#Python_Implementation
    ”“”
    def merc_x(lon):
        r_major = 6378137.000
        return r_major * math.radians(lon)

    def merc_y(lat):
        if lat > 89.5:
            lat = 89.5
        if lat < -89.5:
            lat = -89.5
        r_major = 6378137.000
        r_minor = 6356752.3142
        temp = r_minor / r_major
        eccent = math.sqrt(1 - temp**2)
        phi = math.radians(lat)
        sinphi = math.sin(phi)
        con = eccent * sinphi
        com = eccent / 2
        con = ((1.0 - con) / (1.0 + con))**com
        ts = math.tan((math.pi / 2 - phi) / 2) / con
        y = 0-r_major * math.log(ts)
        return y

    return merc_x(pt[0]), merc_y(pt[1])
→ 2011-09-19