Matplotlib date ticker - exceeds Locator.MAXTICKS error for no apparent reason

16,130

Solution 1

The real issue is that RRuleLocator assumes that the underlying rrule instance's interval variable will have been updated when byminute is set and interval isn't passed in on initialization (it defaults to 1). In fact, interval is completely ignored in rrule (with some small exceptions w.r.t. if filtered is set or not) when byxxx (hour/minute/second etc) is set!

Instead of overriding MAXTICKS, its better just to change your code to include the interval on the MinuteLocator to be 30 as well. This won't change how the final image is drawn as per above (unless you are using filtered).

ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0,30], interval=30))

Granted that while this is just a workaround as well, the estimation check in RRuleLocator's tick_values can be cleaned up to include what is set in the byxxx variables (although that could get messy).

Solution 2

It seems your X axis had too many tick marks for the program to handle.

Try changing

    ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0,30]))

to

    ax.xaxis.set_major_locator(mdates.HourLocator(byhour=[0,1]))

The default maximum number of ticks is 2000 that is locator.MAXTICKS * 2.
Working in minutes you had 2879 ticks That at 1440 minutes per day for two days plus a buffer of 79 ticks.

Changing your x axis to hours gives 48 hours plus the buffer ticks which are well under the 2000 tick limit on the x axis.

Changing the default MAXTICKS to 1500 could work, but it defeats the intended protection.

At this time there is no option for a 30 minute tick mark.

Share:
16,130
Sebastian
Author by

Sebastian

Updated on June 19, 2022

Comments

  • Sebastian
    Sebastian almost 2 years

    When I plot datapoints vs time, spanning over 2 days, and I set a datelocator for 0 and 30 minutes. A major tick for each half hour, matplotlib throws an error. Consider this example:

    from datetime import datetime
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    
    datapoints = 3600*24*2   #2 days, 1 datapoint/second
    data = range(datapoints)  #anydata
    timestamps = [ datetime.fromtimestamp(t) for t in range(datapoints) ]
    
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)   
    ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0,30]))
    
    plt.plot(timestamps,data)
    plt.show()
    

    Then I get the following error:

    RuntimeError: RRuleLocator estimated to generate 2879 ticks from 1970-01-01 01:00:00+00:00 to 1970-01-03 00:59:59+00:00: exceeds Locator.MAXTICKS * 2 (2000)

    2879 ticks is exactly the amount of minutes in that timespan, meaning the estimate is based on 1 tick every minute. However the locator should yield 1 tick every 30 minutes (2 ticks per hour in 48 hour = 96 ticks). Why is the estimate and the real value so far from eachother?

    A workaround would be to raise the MAXTICKS value:

    locator = mdates.MinuteLocator(byminute=[0,30])
    locator.MAXTICKS = 1500
    ax.xaxis.set_major_locator(locator)
    

    That works and the graph nicely shows. However that should not be needed right? Why is this error occuring in the first place? Am I using the datelocator wronly?