Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Crash when using zoom tools on a plot: AutoMinorLocator after MultipleLocator gives "ValueError: Need at least two major ticks to find minor tick locations" #807

Closed
cgra opened this Issue · 2 comments

2 participants

cgra Michael Droettboom
cgra

Run the following code and then zoom in with the zoom-box tool or the cross and right-click drag to zoom in.

from pylab import *
from matplotlib.ticker import MultipleLocator, AutoMinorLocator
plot([0,3],[0,2.2])
ax = gca()
ax.xaxis.set_major_locator(MultipleLocator(0.5))
ax.xaxis.set_minor_locator(AutoMinorLocator(2))
show()

Once MultipleLocator has been called, the auto-reassigning of tick spacing when zooming (either with the zoom box or the cross and right-click drag) does not happen, and then AutoMinorLocator gives the following error because it has "majorstep = majorlocs[1] - majorlocs[0]" and majorlocs has less than 2 elements when zoomed in that far.
"ValueError: Need at least two major ticks to find minor tick locations
( File "/usr/lib/pymodules/python2.7/matplotlib/ticker.py", line 1528, in call )"

cgra

Found with matplotlib 1.1.0, and confirmed by Mike Kaufman on Mar 28 2012 github checkout (see matplotlib-users mailing list, thread view of http://sourceforge.net/mailarchive/message.php?msg_id=29040134).

Michael Droettboom mdboom was assigned
cgra

Ok, I took a look at the source of the error, class AutoMinorLocator(Locator), in ticker.py, and came up with a very simple fix that involves editing 1 line and adding 2 lines.

Inside

class AutoMinorLocator(Locator):

change the following

        except IndexError:
            raise ValueError('Need at least two major ticks to find minor tick locations')

to

        except IndexError:
            majorstep = 0

and change the following

        t0 = majorlocs[0]
        tmin = np.ceil((vmin - t0) / minorstep) * minorstep
        tmax = np.floor((vmax - t0) / minorstep) * minorstep
        locs = np.arange(tmin, tmax, minorstep) + t0
        cond = np.abs((locs - t0) % majorstep) > minorstep/10.0
        locs = locs.compress(cond)
        locs = []

to

        if len(majorlocs) > 0:
            t0 = majorlocs[0]
            tmin = np.ceil((vmin - t0) / minorstep) * minorstep
            tmax = np.floor((vmax - t0) / minorstep) * minorstep
            locs = np.arange(tmin, tmax, minorstep) + t0
            cond = np.abs((locs - t0) % majorstep) > minorstep/10.0
            locs = locs.compress(cond)
        else:
            locs = []

The second change could also be done with a try/except instead of an if/else, e.g.

        try:
            t0 = majorlocs[0]
            ...
        except IndexError:
            locs = []

Then when there are less than 2 major ticks visible on an axis, the minor ticks are not shown at all. (When zooming back out, the minor ticks are shown again.) This seems to be the best solution, since there does not seem to be an axis property to get tick locations that are outside the plot view range.

How does one go about submitting this to the matplotlib package?

Benjamin Root WeatherGod referenced this issue from a commit in WeatherGod/matplotlib
Benjamin Root WeatherGod Implements @cgra (Christopher Graves) suggestion for issue #807. a6a9624
cgra cgra closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.