Skip to content

Instantly share code, notes, and snippets.

@tonysyu
Created January 31, 2012 01:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonysyu/1708133 to your computer and use it in GitHub Desktop.
Save tonysyu/1708133 to your computer and use it in GitHub Desktop.
Hacky attempt at automatically adjusting the number of tick labels
"""
Automatically adjust the number of ticklabels based on label width.
This is a hacky attempt at an auto tick locator and misses *many* use cases.
To test, stretch and shrink the x-axis.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import matplotlib.axis as maxis
class AutoLocator(mtick.MaxNLocator):
"""Tick locator that tries to be smart.
Parameters
----------
nbins : int
Maximum number of bins---i.e., tick intervals.
steps : list of numbers
Allowable steps for lowest displayed digit. This is a sequence of
"nice" numbers starting with 1 and ending with 10.
"""
def __init__(self, nbins=9, steps=[1, 2, 5, 10], fontsize=None):
mtick.MaxNLocator.__init__(self, nbins=nbins, steps=steps)
if fontsize is None:
fontsize = plt.rcParams['font.size']
self.fontsize = fontsize
self._nbins_cached = nbins
def bin_boundaries(self, vmin, vmax):
"""Return bin boundaries (a.k.a. tick locations)."""
# The calculation of the label width should actually depend on the
# tick Formatter instance.
label_width = max(len('%g' % v) for v in (vmin, vmax))
# This is only an approximate calculation of the label width
label_px_width = label_width * self.fontsize
w, h = self.axis.axes.figure.canvas.get_width_height()
if not isinstance(self.axis, maxis.XAxis):
raise NotImplementedError("Currently only XAxis is supported.")
# Use figure width to calculate the number of bins---only valid for x-axis.
# The following nbins calculation is approximate since it should vary
# with subplot parameters---i.e. padding on the left and right of
# subplots and multiple columns in a subplot grid.
self._nbins = min(self._nbins_cached, int(w / label_px_width))
return mtick.MaxNLocator.bin_boundaries(self, vmin, vmax)
if __name__ == '__main__':
fig, ax = plt.subplots()
x = np.linspace(0, 7000000)
y = np.sin(x)
ax.plot(x, y)
ax.xaxis.set_major_locator(AutoLocator())
plt.tight_layout()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment