FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Update legends in plots subclassed from animation.TimedAnimation · Issue #13252 · matplotlib/matplotlib · GitHub

Repository navigation

Update legends in plots subclassed from animation.TimedAnimation #13252

Closed

Description

Hi, I want to update the legend with the latest y-value in an animated plot. The graph animation is done as the following official matplotlib example, where the implementation of the animated figures are done by subclassing the animation.TimedAnimation class. To exemplify the issue I've modified the example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import matplotlib.animation as animation

class SubplotAnimation(animation.TimedAnimation):
    def __init__(self):
        fig = plt.figure()
        self.ax1 = fig.add_subplot(1, 2, 1)
        self.ax2 = fig.add_subplot(2, 2, 2)
        self.ax3 = fig.add_subplot(2, 2, 4)

        self.t = np.linspace(0, 80, 400)
        self.x = np.cos(2 * np.pi * self.t / 10.)
        self.y = np.sin(2 * np.pi * self.t / 10.)
        self.z = 10 * self.t

        self.ax1.set_xlabel('x')
        self.ax1.set_ylabel('y')
        self.line1 = Line2D([], [], color='black', label='_nolegend_')
        self.line1a = Line2D([], [], color='red', linewidth=2, label='_nolegend_')
        self.line1e = Line2D(
            [], [], color='red', marker='o', markeredgecolor='r', label="val = 0")
        self.ax1.add_line(self.line1)
        self.ax1.add_line(self.line1a)
        self.ax1.add_line(self.line1e)
        self.ax1.set_xlim(-1, 1)
        self.ax1.set_ylim(-2, 2)
        self.ax1.set_aspect('equal', 'datalim')

        self.ax2.set_xlabel('y')
        self.ax2.set_ylabel('z')
        self.line2 = Line2D([], [], color='black')
        self.line2a = Line2D([], [], color='red', linewidth=2)
        self.line2e = Line2D(
            [], [], color='red', marker='o', markeredgecolor='r')
        self.ax2.add_line(self.line2)
        self.ax2.add_line(self.line2a)
        self.ax2.add_line(self.line2e)
        self.ax2.set_xlim(-1, 1)
        self.ax2.set_ylim(0, 800)

        self.ax3.set_xlabel('x')
        self.ax3.set_ylabel('z')
        self.line3 = Line2D([], [], color='black')
        self.line3a = Line2D([], [], color='red', linewidth=2)
        self.line3e = Line2D(
            [], [], color='red', marker='o', markeredgecolor='r')
        self.ax3.add_line(self.line3)
        self.ax3.add_line(self.line3a)
        self.ax3.add_line(self.line3e)
        self.ax3.set_xlim(-1, 1)
        self.ax3.set_ylim(0, 800)

        self.ax1.legend()
        animation.TimedAnimation.__init__(self, fig, interval=50, blit=True)

    def _draw_frame(self, framedata):
        i = framedata
        head = i - 1
        head_slice = (self.t > self.t[i] - 1.0) & (self.t < self.t[i])

        self.line1.set_data(self.x[:i], self.y[:i])
        self.line1a.set_data(self.x[head_slice], self.y[head_slice])
        self.line1e.set_data(self.x[head], self.y[head])
        self.ax1.get_legend().texts[0].set_text("val = %s" % self.y[head])

        self.line2.set_data(self.y[:i], self.z[:i])
        self.line2a.set_data(self.y[head_slice], self.z[head_slice])
        self.line2e.set_data(self.y[head], self.z[head])

        self.line3.set_data(self.x[:i], self.z[:i])
        self.line3a.set_data(self.x[head_slice], self.z[head_slice])
        self.line3e.set_data(self.x[head], self.z[head])

        self._drawn_artists = [self.line1, self.line1a, self.line1e,
                               self.line2, self.line2a, self.line2e,
                               self.line3, self.line3a, self.line3e]

    def new_frame_seq(self):
        return iter(range(self.t.size))

    def _init_draw(self):
        lines = [self.line1, self.line1a, self.line1e,
                 self.line2, self.line2a, self.line2e,
                 self.line3, self.line3a, self.line3e]
        for l in lines:
            l.set_data([], [])

ani = SubplotAnimation()
# ani.save('test_sub.mp4')
plt.show()

The legeend will not update unless the self._drawn_artists is commented out. But I want to keep using that inherited method otherwise the window/animation is lagging seriously.

Activity

  1. ImportanceOfBeingErnest commented on Jan 21, 2019

    Member

    Worth noting that the example you refer to has been removed from the docs in #10125. The reason was

    relies on subclassing private attributes of TimedAnimation, would
    better be replaced by a FuncAnimation example, overly complex

    I think one would rather create the figure, axes, lines etc. outside of any subclass and create a FuncAnimation that updates the lines.

    Concerning the legend, it should be possible to blit that as well as long as it (a) is returned by the animating function, (b) spacially resides inside an axes.

  2. tkgit123 commented on Jan 22, 2019

    Author

    Worth noting that the example you refer to has been removed from the docs in #10125. The reason was

    relies on subclassing private attributes of TimedAnimation, would
    better be replaced by a FuncAnimation example, overly complex

    I think one would rather create the figure, axes, lines etc. outside of any subclass and create a FuncAnimation that updates the lines.

    Concerning the legend, it should be possible to blit that as well as long as it (a) is returned by the animating function, (b) spacially resides inside an axes.

    Thank you for your reply! I've looked into FuncAnimation, but I didn't get it to work with pyQt.
    ani = FuncAnimation(self.fig, self.animate, interval=50, blit=True)
    The above line won't run the method self.animate(). No warnings/errors, it will just not enter that method.

    Besides I've already have code that is implemented like the subclassed example above. Is there a way to blit: legend, xTicks and change ylimit inside the subclassed method def _draw_frame(self, framedata) aswell?

  3. ImportanceOfBeingErnest commented on Jan 28, 2019

    Member

    The above line won't run the method self.animate(). No warnings/errors, it will just not enter that method.

    Usually that happens if ani gets garbage collected. Make sure you keep a reference to the FuncAnimation instance.

    Is there a way to blit: legend, xTicks and change ylimit

    Once you start blitting everything, you may as well not blit at all. There will be no improvement in speed in such case.

  4. jklymak commented on Oct 1, 2019

    Member

    Closing as quite old, and I don't think there is an action here. Follow up on https://discourse.matplotlib.org if there is further discussion...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL