Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Drop event_source.interval reset #28997

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

Closed
wants to merge 0 commits into from
Closed

Drop event_source.interval reset #28997

wants to merge 0 commits into from

Conversation

Lucx33
Copy link
Contributor

@Lucx33 Lucx33 commented Oct 20, 2024

PR summary

This PR fixes the TimedAnimation event loop by removing the interval reset within the _step() method. This ensures that the animation runs at the expected frame rate, regardless of the duration of the callback execution. Couldnt find examples where pileup happens.

PR checklist

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@dopplershift
Copy link
Contributor

Not setting the delay in that spot is going to cause any loop_delay to become permanent after one loop.

I'll also note that it seems that loop_delay is broken on macOS at the moment.

@dopplershift
Copy link
Contributor

The dynamic_image.py example is a good place to test this.

@tacaswell
Copy link
Member

I suspect that what we want to be doing to better hit the target frame rate is to time the call to super()._step and set self.event_source.interval = max(0, self._interval - draw_time)

@greglucas
Copy link
Contributor

I wonder if the real culprit is that in a lot of backends we are "stopping"/"starting" a new timer every time the interval property gets updated. I'm curious if we should put a guard around this property update to only trigger if self._interval != interval

self._timer_set_interval()

Our timer interval should just keep going at the requested rate under the hood, so updating it to depend on the underlying function call time seems like it would lead to issues and a constantly moving target. My thought with the update guard is that currently we are bringing that draw-time into the underlying timer every time we call that update function without realizing it by calling start() based on the event updates.

This diff does provide 200ms in the provided example in #28647

diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py
index 95ed49612b..f5a41c140f 100644
--- a/lib/matplotlib/backend_bases.py
+++ b/lib/matplotlib/backend_bases.py
@@ -1042,6 +1042,8 @@ class TimerBase:
         """
         self.callbacks = [] if callbacks is None else callbacks.copy()
         # Set .interval and not ._interval to go through the property setter.
+        self._interval = None
+        self._single = None
         self.interval = 1000 if interval is None else interval
         self.single_shot = False
 
@@ -1085,8 +1087,9 @@ class TimerBase:
         # milliseconds, and some error or give warnings.
         # Some backends also fail when interval == 0, so ensure >= 1 msec
         interval = max(int(interval), 1)
-        self._interval = interval
-        self._timer_set_interval()
+        if self._interval != interval:
+            self._interval = interval
+            self._timer_set_interval()
 
     @property
     def single_shot(self):
@@ -1095,8 +1098,9 @@ class TimerBase:
 
     @single_shot.setter
     def single_shot(self, ss):
-        self._single = ss
-        self._timer_set_single_shot()
+        if self._single != ss:
+            self._single = ss
+            self._timer_set_single_shot()
 
     def add_callback(self, func, *args, **kwargs):
         """

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Waiting for author
Development

Successfully merging this pull request may close these issues.

[MNT]: TimedAnimation event loop interval
4 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.