I would like to plot a graph of some experimental data which is sampled at a relatively high rate, but approximates a smooth curve using markers spaced at equal arc-length i
Since matplotlib 1.4, you can use markevery with real numbers to achieve this.
Documentation: http://matplotlib.org/api/lines_api.html#matplotlib.lines.Line2D.set_markevery
Example:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10*np.pi, 1000)
y = np.sin(x*2) + np.sin(x + 1)
plt.plot(x, y, marker='o', markevery=0.05)
plt.show()
I think I have put together a relatively good solution. The only problem is taking the data ratio into account in a way that also uses information about the aspect ratio of the final plot. I've not found a reliable way to do this, although this function will accept a data ratio so you can play until the output looks right:
def spacedmarks(x, y, Nmarks, data_ratio=None):
import scipy.integrate
if data_ratio is None:
data_ratio = plt.gca().get_data_ratio()
dydx = gradient(y, x[1])
dxdx = gradient(x, x[1])*data_ratio
arclength = scipy.integrate.cumtrapz(sqrt(dydx**2 + dxdx**2), x, initial=0)
marks = linspace(0, max(arclength), Nmarks)
markx = interp(marks, arclength, x)
marky = interp(markx, x, y)
return markx, marky
Example of use (this is suitable for pylab mode in iPython):
x = linspace(0, 10*pi, 1000)
y = sin(x*2) + sin(x+1)
plot(x, y)
markx, marky = spacedmarks(x, y, 80)
plot(markx, marky, 'o', color='blue')
Result: