matplotlib animation vs python event loop (event loop gives choppy results)

67 views Asked by At

The matplotlib FuncAnimation timer works significantly better than either python event loop or main thread while-loop.

I have a script that sends a UDP buffer to a microcontroller to control LEDs. I plot and "mock" these LEDs with matplotlib, and can also send the UDP buffer in the FunAnimation callback.

When the udp packet is sent within the FuncAnimation Timer callback, the packet is received in a smooth, timely manner. When using the python event-loop, threads, or simple sleep/while-loop it is inconsistent and choppy.

Here is a redacted example of the matplotlib FunAnimation code (which works great):

# matplotlib use case
def update(_):
    send_udp_buffer()
    return scat # scatter plot of LEDs

ani = animation.FuncAnimation(
    fig=fig,
    func=update,
    frames=60,
    interval=50, # 50 milliseconds
)

Here is an example of generic while-loop based code I've tried (which ends up choppy and inconsistent):

# Standard while-loop
while True:
    send_udp_buffer()
    time.sleep(.05)

# python event-loop

import asyncio

async def periodic():
    while True:
        send_udp_buffer()
        await asyncio.sleep(0.05)

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = loop.create_task(periodic())

I am on MacOSX, so the Timer used by FuncAnimation is the TimerMac, which is a wrapper around NSTimer. I have tried including this and utilizing it, but it there seems to be some hidden implementation details.

My Question

Why does the event loop not act in a similar manner to the matplotlib Timer, and how can I replicate this behavior?

1

There are 1 answers

0
user22798228 On

My assumption was incorrect, the FuncAnimation was not better or smoother than other methods. The FuncAnimation does not actually use the interval supplied to it. It stays at around 100ms. The FuncAnimation appeared better because of the delay between UDP packets, so my 50ms delay was too aggressive.

However, if anyone is curious about using NSTimer in python there is a library that wraps obj-c classes, pyobjc