public
Last active

Hacky attempt at automatically adjusting the number of tick labels

  • Download Gist
auto_ticker_example.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
"""
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()

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.