Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matplotlib.dates.DayLocator cannot handle invalid input #6935

Closed
chrisjcameron opened this issue Aug 10, 2016 · 1 comment · Fixed by #6955
Closed

matplotlib.dates.DayLocator cannot handle invalid input #6935

chrisjcameron opened this issue Aug 10, 2016 · 1 comment · Fixed by #6955
Labels
Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues
Milestone

Comments

@chrisjcameron
Copy link

This is a relatively minor bug in the way DayLocator tries to report an error message when running the tick_values() method. It is unable to report the invalid input because the invalid input causes a type error while formatting the error message. To be clear, the issue is not that the class breaks with invlaid input but how it breaks with invalid input.

The method could check for Nan or Inf numpy.float64 values before trying to use the %d format, switch to the %f format or catch zero-width intervals at initialization time.

Matplotlib 1.5.2, Anaconda Python 2.7 on Mac OSX

    import datetime
    import matplotlib
    import matplotlib.pyplot as plt
    from matplotlib.dates import DateFormatter, DayLocator

    vals = range(22)
    dates = [datetime.datetime(2016, 8, 1, x, 20, 20) for x in range(22)]

    plt.plot(dates, vals)
    ax = plt.subplot(111)
    ax.xaxis.set_major_locator(DayLocator(interval=0))  #causes exception
/Users/cjc73/anaconda/lib/python2.7/site-packages/matplotlib/axis.pyc in iter_ticks(self)
    892         Iterate through all of the major and minor ticks.
    893         """
--> 894         majorLocs = self.major.locator()
    895         majorTicks = self.get_major_ticks(len(majorLocs))
    896         self.major.formatter.set_locs(majorLocs)

/Users/cjc73/anaconda/lib/python2.7/site-packages/matplotlib/dates.pyc in __call__(self)
    812             return []
    813 
--> 814         return self.tick_values(dmin, dmax)
    815 
    816     def tick_values(self, vmin, vmax):

/Users/cjc73/anaconda/lib/python2.7/site-packages/matplotlib/dates.pyc in tick_values(self, vmin, vmax)
    842                 'RRuleLocator estimated to generate %d ticks from %s to %s: '
    843                 'exceeds Locator.MAXTICKS * 2 (%d) ' % (estimate, vmin, vmax,
--> 844                                                         self.MAXTICKS * 2))
    845 
    846         dates = self.rule.between(vmin, vmax, True)

TypeError: %d format: a number is required, not numpy.float64
@anntzer
Copy link
Contributor

anntzer commented Aug 10, 2016

Looks like we're having a premature optimization:

        # estimate the number of ticks very approximately so we don't
        # have to do a very expensive (and potentially near infinite)
        # 'between' calculation, only to find out it will fail.
        nmax, nmin = date2num((vmax, vmin))
        estimate = (nmax - nmin) / (self._get_unit() * self._get_interval())
        # This estimate is only an estimate, so be really conservative
        # about bailing...
        if estimate > self.MAXTICKS * 2:
            raise RuntimeError(
                'RRuleLocator estimated to generate %d ticks from %s to %s: '
                'exceeds Locator.MAXTICKS * 2 (%d) ' % (estimate, vmin, vmax,
                                                        self.MAXTICKS * 2))

        dates = self.rule.between(vmin, vmax, True)

I'd just strip out everything but the last line and call Locator.raise_if_exceeds with the actual tick count.

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Aug 13, 2016
@tacaswell tacaswell added the Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues label Aug 13, 2016
LindyBalboa pushed a commit to LindyBalboa/matplotlib that referenced this issue Aug 18, 2016
Check that interval parameter is an integer greater than zero.

Delete unuseful 'optimization' meant to prevent exceeding the
MAXTICKS variable. During testing it seemed ineffective. The
following Locator.raise_if_exceeds exception was triggered first
anyways.

resolves matplotlib#6935
LindyBalboa pushed a commit to LindyBalboa/matplotlib that referenced this issue Aug 18, 2016
LindyBalboa pushed a commit to LindyBalboa/matplotlib that referenced this issue Aug 21, 2016
Check that interval parameter is an integer greater than zero.

Delete unuseful 'optimization' meant to prevent exceeding the
MAXTICKS variable. During testing it seemed ineffective. The
following Locator.raise_if_exceeds exception was triggered first
anyways.

resolves matplotlib#6935
LindyBalboa pushed a commit to LindyBalboa/matplotlib that referenced this issue Aug 21, 2016
@QuLogic QuLogic modified the milestones: 2.0 (style change major release), 2.1 (next point release) Aug 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants