8000 Daylocator causes frozen computer when used with FuncAnimation · Issue #20202 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
Daylocator causes frozen computer when used with FuncAnimation #20202
Closed
@Spock-to-Kirk

Description

@Spock-to-Kirk

Bug report

This is an existing bug that is already known but it might be prevented by using extra initialization steps.
I hope someone can guide me.

Error: "Locator attempting to generate 4018 ticks ([10775.0, ..., 14792.0]), which exceeds Locator.MAXTICKS (40)."

Day locator is generating far too many day or hour ticks (thousands). This is causing to slow down the code to freeze for minutes or to completely freeze computer. I have seen Daylocator working properly so it may only happen in conjunction with FuncAnimation. My code must update the graph every few seconds. I use FuncAnimation wich an update function to do that.
I think the combination of both causes this issue. If I cannot solve it I must stop using Matplotlib. More people might be looking for it. That is the reason for posting.

Conditions and versions

Using OS Ubuntu 18.04
Python: 3.6.9
Matplotlib: 3.3.3
Matplotlib backend: Qt5Agg

The bug

The bug is explained in detail here:
runningcode11 and here stackoverflow

It is caused by missing initialization in rrulelocator. I tried to set this by running SecondLocator, MinuteLocation, HourLocator before. This is not working.

Code for reproduction

#!/usr/bin/python3
# mathplotlib example


import warnings
warnings.filterwarnings( "ignore", module = "matplotlib\..*" )

import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.animation import FuncAnimation


# timing variables
update_int = 100    # update interval in ms
rep_del = 1000      # delay after each animation run


# np line space does not support datetime objects. Function to create a np line space.
# start, end are date_time objects
def date_linespace(start, end, steps):
    
    delta = (end - start) / steps
    increments = range(0, steps) * np.array([delta]*steps)
    return start + increments


def init():
    print("init")
    # ax is of type AxesSubplot
    #ax.set_xlim(0, 2*np.pi)
    
    ax.set_xlim(start_datetime_object, end_datetime_object)
    print("x limit")
    print(ax.get_xlim())

    ax.set_ylim(0, 3)
    print("y limit")
    print(ax.get_ylim())

    return line,    # the comma makes the return value iterable



def update(frame):

    # frame is numpy float64
    print("this is a frame")
    y = fake_y_data.pop(0)    # take one element from the array

    xdata.append(frame)
    #ydata.append(np.sin(frame) + y_offset)
    ydata.append(y)
    
    print("x data")
    print(xdata)
    print("y data")
    print(ydata)
    line.set_data(xdata, ydata)

    return line,


# use two sub plots
fig, ax = plt.subplots(figsize=(5, 4))  # size of graphic
xdata, ydata = [], []
fake_y_data = [2,1,0,1,1,3,0,1,2,3,2,3,0,3,3,1,2,0,2,1]   # test data

# format line
line, = plt.plot([], [], '-r')     # - = solid line, r = red. Must be iterable ","

# circumventing a bug //// this is not working
seclocator = mdates.SecondLocator(interval=2000) 
minlocator = mdates.MinuteLocator(byminute=range(60), interval=1000) 
hourlocator = mdates.HourLocator(byhour=range(24), interval=1200)

seclocator.MAXTICKS  = 10
minlocator.MAXTICKS  = 10
hourlocator.MAXTICKS  = 10


# Major ticks every day
fmt_day = mdates.DayLocator(interval=1)
fmt_day.MAXTICKS = 40  # has NO effect
ax.xaxis.set_major_locator(fmt_day)

# Text in the x axis will be displayed in 'YYYY-mm-dd' format.
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

# create x time series data: start > end in n frames
# init frames. X- coordinates of type: numpy.ndarray
start_datetime_object = datetime.datetime(2019, 8, 8)
end_datetime_object = datetime.datetime(2019, 8, 23)
frames = date_linespace(start_datetime_object, end_datetime_object, 10)

ani = FuncAnimation(fig, update, frames, init_func=init, blit=True, interval=update_int, repeat_delay=rep_del, repeat=False)

plt.title("my test graph")
plt.xlabel("x-axis")
plt.ylabel("y-axis")

# Right corner coordinates box
ax.format_xdata = mdates.DateFormatter('%Y-%m-%d')
ax.format_ydata = lambda x: f'kwh{x:.2f}'  # Format x value in kwh
ax.grid(True)

# Rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them.
fig.autofmt_xdate()                                    # will rotate 30 deg to fit
plt.setp(ax.xaxis.get_majorticklabels(), rotation=30)  # rotate manually (not required)

# show the plot and loop
plt.show()

Actual outcome

The support for Qt4  was deprecated in Matplotlib 3.3 and will be removed two minor releases later.
  module = self._original_import(*args, **kw)
Locator attempting to generate 4018 ticks ([10775.0, ..., 14792.0]), which exceeds Locator.MAXTICKS (40).
Locator attempting to generate 4018 ticks ([10775.0, ..., 14792.0]), which exceeds Locator.MAXTICKS (40).
Locator attempting to generate 4018 ticks ([10775.0, ..., 14792.0]), which exceeds Locator.MAXTICKS (40).
Locator attempting to generate 4018 ticks ([10775.0, ..., 14792.0]), which exceeds Locator.MAXTICKS (40).

Expected outcome

Proper initialization should avoid create all those ticks an memory corruption that is coming from it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    0