def elevColorMap(fIN, fOUT='elev.png'):
'''PLOT ELEVATION PROFILE AND GRADIENT FROM MAPMYRIDE.COM DATA EXPORT
INPUT
fIN : str (req'd)
This is the file name of the data exported from mapmyride.com
Needs to be in a .csv (comma-separated variable) format. Plot
fOUT : str (opt)
This is the file image of the image output by this utility.
Defaults to 'elev.png'. pl.savefig command can infer file
format from most common image extensions (e.g., .pdf, .gif...)
OUTPUT
NONE
EXAMPLE
>>> os.chdir('users/paul/python/misc')
>>> from bikes import *
>>> elevColorMap('users/paul/desktop/elev.csv', 'tues.jpg')
+-----------------------------------+
| Paul M. Hobson __o |
| pmhobson@gmail _`\<,_ |
| 2009/07/30 (_)/ (_) |
+-----------------------------------+
'''
import pylab as pl
from numpy import floor, ceil
x,y,ca,cd = pl.loadtxt(fIN, delimiter=',', skiprows=1, unpack=True)
Y = y * 10.
C = int(len(x))
R = int(ceil(max(Y)))
g = pl.zeros([C,1])
for n in range(1,C):
g[n] = (y[n] - y[n-1])/(x[n]-x[n-1])*100
g = smoothData(g,15,1)
yin = pl.arange(R)
p = pl.zeros([R,C])
for n in range(C):
p[0:Y[n],n] = g[n]
g1 = int(floor(min(g)))
g2 = int(ceil(max(g)))
V = range(g1,g2, 1)
fig = pl.figure(1, figsize=(6,3.5))
pl.clf()
G = pl.contourf(x/1000, yin/10, p, V, antialiased=True)
x2 = x.copy()
x2[-1] += 10
xu,gu = pl.poly_between(x2,y,max(y))
pl.fill(xu/1000,gu, facecolor='white', edgecolor='white')
elv = pl.plot(x/1000, y, 'k-', lw=2.0, label='Elevation')
cbar = pl.colorbar(G, ticks=range(g1,g2+1))
cbar.ax.set_ylabel('Gradient (%)', fontsize=10)
cl = pl.getp(cbar.ax, 'ymajorticklabels')
pl.setp(cl, fontsize=10)
pl.grid()
pl.xlabel('Distance Ridden (km)')
pl.ylabel('Elevation (m above MSL)')
figFormat(1, ff='sans-serif')
pl.savefig(fOUT)
return fig, cbar
def figFormat(fig_num, fs=10, ff='serif', fw='normal'):
'''QUICKLY FORMAT MATPLOTLIB FIGURES
TODO:
Add functionality to handle colorbars
Input:
fig_num : int (req'd)
figure handle of figure to modified
fs : int (optional)
font size (points) figure text (default = 10)
ff : str (optional)*
font family of figure text (default = 'serif')
fw : str (optional)**
font weight of figure text (default = 'normal')
*possible ff (font-families):
[ 'serif' | 'sans-serif' | 'cursive' | 'fantasy' | 'monospace' ]
(you should probably stick to serif, sans-serif, or monospace)
**possible fw (font-weights):
[ 'light' | 'normal' | 'bold' | 'heavy' ]
(you should probably stick with normal...i.e., don't specify this)
Output:
NONE
Example:
>>> from pylab import *
>>> from MiscUtils import *
>>> x = arange(16)
>>> y = x**2 + 5*x - 9
>>> figure(1)
>>> h1 = plot(x,y,'ko', label='test1')
>>> h2 = plot(x,y,'k-', label='test2')
>>> xlabel('X-data')
>>> ylabel('Y-data')
>>> legend()
>>> figFormat(1, fs=12, ff='sans-serif')
>>> savefig('test.pdf')
+-----------------------------------+
| Paul M. Hobson __o |
| pmhobson@gmail _`\<,_ |
| 2009/05/31 (_)/ (_) |
+-----------------------------------+
'''
import pylab as pl # bring in pylab module
pl.figure(fig_num) # bring spec'd figure to focus
X = pl.getp(pl.gca(), 'xticklabels') # get the x-axis labels
Y = pl.getp(pl.gca(), 'yticklabels') # get the y-axis labels
for i in range(len(X)): # format x-axis
pl.setp(X[i], family=ff, size=fs)
for i in range(len(Y)): # format y-axis
pl.setp(Y[i], family=ff,size=fs)
XL = pl.getp(pl.gca(), 'xlabel') # format x-axis labels
pl.xlabel(XL, size=fs, family=ff)
YL = pl.getp(pl.gca(), 'ylabel') # format y-axis labels
pl.ylabel(YL, size=fs, family=ff)
try: # format the legend if there is one
L = pl.getp(pl.gca(),'legend')
LC = pl.getp(L, 'children')
if len(LC) > 0:
pl.setp(LC[-1], size=fs, family=ff)
except:
L = 1
def smoothData(x, d, type):
'''
SMOOTHS NOISEY DATA, NOTHING SCIENTIFIC ABOUT THIS
'''
from numpy import zeros, mean, mod
X = zeros(len(x)) # initialize output
if type == 1: # for a rolling average sceme
for n in range(len(x)):
if n-d < 0:
n = range(0, n+d+1)
elif n+d >= len(x):
n = range(n-d, len(x))
else:
n = range(n-d, n+d+1)
X[n] = mean(x[n])
elif type == 2: # resample at lower frequency
# NOT FINISHED
N = len(x) - mod(len(x),d)
X = zeros(N)
for n in range(0,N,d):
m = n + d
X[n] = mean(x[n:m])
else:
print 'invalid averaging type'
X = x
return X
ATTN: C. Kelly, S. Kingry, B. Smith, et al...
My Python code to plot elevation profiles like this:
Alls you need for the color mapped profile in comma separated x and z values.



I feel that these graphs
I feel that these graphs should always have X and Y on the same scale, that way we can see what the hills actually looked like. Think of it as a new way to draw a landscape.
45 degrees
if you want to better distinguish between the pitch of climbs, 45 degree slopes (on average) would be ideal:
http://www.processtrends.com/pg_data_vis_bank_to_45.htm
http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR (look for the "Aspect ratio" section)
.
putting rides of about 50 - 70 miles on the same scale as the vertical axis makes it difficult to see even climbs with 4000+ ft of elevation gain.
also, you've got the source code, YOU can make it do want you want it to do
FYI, did some stuff you can't
FYI, did some stuff you can't to so code looks better now :)
.
i had the "code" tags wrapped around the whole thing. why do line breaks, break things?
Here are the horribile
Here are the horribile details: http://www.lullabot.com/articles/drupal_input_formats_and_filters
Basically, the default input filter here buts in lil br tags and p tags as it thinks are needed so that people don't have to type html, but it breaks some special use cases and browsers handle funky tag nesting differently, especially with things like pre/code.
thanks, ck
I was having a hard time parsing it before.