To extend @leal26's answer into something more flexible (i.e. for if we want to zoom/pan around the plot), we can use the matplotlib.ticker
module.
The locations of the ticks can be set using ax.xaxis.set_major_locator
(and ax.yaxis.set_major_locator
) with a ticker.MultipleLocator
, using a base = pi/2
.
We can then use a ticker.FuncFormatter
to set the format of the tick labels (this time using ax.xaxis.set_major_formatter
. There are several special cases we have to account for (e.g. 1 in the numerator and/or denominator, etc.). See the fracformat
function below.
Notice also that we have to use a raw string (r
prefix) and double braces for the LaTeX formatting.
The real advantage here is that we can easily change the tick locations, the plot limits, etc., without having to manually redefine the tick labels every time.
Finally, I also slightly changed your script to make use of matplotlib
's object-oriented approact, so that we create a Figure
instance with plt.figure
, an Axes
instance (ax
) with fig.add_subplot
, and then for everything else, we call the relevant functions from ax
.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from fractions import Fraction
t = np.linspace(0, 4*np.pi, 150)
fig = plt.figure()
ax = fig.add_subplot(111)
theGrid = np.outer(np.sin(t), np.sin(t))
ax.set_xlim(0, 4*np.pi) #forces an exact fit!
ax.set_ylim(0, 4*np.pi) #ditto!
def fracformat(x,pos):
frac = Fraction(x/np.pi)
if frac.numerator == 0:
return 0
elif frac.numerator == frac.denominator:
return r"$\pi$"
elif frac.numerator == 1:
return r"$\frac{{ \pi }}{{ {:2d} }}$".format(frac.denominator)
elif frac.denominator == 1:
return r"${:2d} \pi$".format(frac.numerator)
else:
return r"$\frac{{ {:2d} \pi }}{{ {:2d} }}$".format(frac.numerator,frac.denominator)
ax.xaxis.set_major_locator(ticker.MultipleLocator(np.pi/2.))
ax.yaxis.set_major_locator(ticker.MultipleLocator(np.pi/2.))
ax.xaxis.set_major_formatter(ticker.FuncFormatter(fracformat))
ax.yaxis.set_major_formatter(ticker.FuncFormatter(fracformat))
ax.pcolormesh(t, t, theGrid)
plt.show()
I increased the plot limits to 4*pi
to show how easy it is to extend this to different ranges, with minimal effort.
