fastplotlib / fastplotlib

Next-gen fast plotting library running on WGPU using the pygfx rendering engine
https://fastplotlib.readthedocs.io/
Apache License 2.0
367 stars 33 forks source link

Animations can be difficult to debug #497

Open kushalkolar opened 2 months ago

kushalkolar commented 2 months ago

By using the wgpu logger:

logger = logging.getLogger("wgpu")

class Handler(logging.Handler):
    def emit(self, record):
        print(logging.Formatter().format(record))

logger.addHandler(Handler())

If I try something simple like this:

fig = fpl.Figure()

img = np.random.rand(10, 10)
ig = fig[0, 0].add_image(img)

def update(subplot):
    ig.data = np.random.rand(10, 20)

fig[0, 0].add_animations(update)
fig.show()

I get a larger traceback but only the first part is relevant to the issue in the animation function:

Draw error
Traceback (most recent call last):
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/_gui_utils.py", line 77, in log_exception
    yield
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/base.py", line 135, in _draw_frame_and_present
    self.draw_frame()
  File "/home/kushal/repos/fastplotlib/fastplotlib/layouts/_figure.py", line 395, in render
    self._call_animate_functions(self._animate_funcs_pre)
  File "/home/kushal/repos/fastplotlib/fastplotlib/layouts/_figure.py", line 529, in _call_animate_functions
    fn(self)
  File "/tmp/ipykernel_2654463/1664422237.py", line 8, in update
    fig[0, 0].graphics[0].data = np.random.rand(10, 20)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_base.py", line 185, in __setattr__
    attr._set(value)
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_features/_base.py", line 308, in _set
    self[:] = value
    ~~~~^^^
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_features/_data.py", line 139, in __setitem__
    self.buffer.data[key] = value
    ~~~~~~~~~~~~~~~~^^^^^
ValueError: could not broadcast input array from shape (10,20) into shape (10,10)
Present error
Traceback (most recent call last):
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/_gui_utils.py", line 77, in log_exception
    yield
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/base.py", line 138, in _draw_frame_and_present
    return self._canvas_context.present()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/offscreen.py", line 71, in present
    raise RuntimeError(msg)
RuntimeError: present() is called without a preceeding call to get_current_texture(). Note that present() is usually called automatically after the draw function returns.
kushalkolar commented 2 months ago

So if I use wgpu.gui.base.log_exception in Figure._call_animate_functions I can at least give it a more useful name:

with log_exception(f"Animation error in {fn}"):
  fn(sefl)

Gives this, not sure why it's also showing the error with Ordered2FragmentBlender

Animation Error in <function update at 0x7f685b1cc400>
Traceback (most recent call last):
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/_gui_utils.py", line 77, in log_exception
    yield
  File "/home/kushal/repos/fastplotlib/fastplotlib/layouts/_figure.py", line 531, in _call_animate_functions
    fn(self)
  File "/tmp/ipykernel_2665047/1664422237.py", line 8, in update
    fig[0, 0].graphics[0].data = np.random.rand(10, 20)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_base.py", line 185, in __setattr__
    attr._set(value)
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_features/_base.py", line 308, in _set
    self[:] = value
    ~~~~^^^
  File "/home/kushal/repos/fastplotlib/fastplotlib/graphics/_features/_data.py", line 139, in __setitem__
    self.buffer.data[key] = value
    ~~~~~~~~~~~~~~~~^^^^^
ValueError: could not broadcast input array from shape (10,20) into shape (10,10)
Draw error
Traceback (most recent call last):
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/_gui_utils.py", line 77, in log_exception
    yield
  File "/home/kushal/venvs/mescore/lib/python3.11/site-packages/wgpu/gui/base.py", line 135, in _draw_frame_and_present
    self.draw_frame()
  File "/home/kushal/repos/fastplotlib/fastplotlib/layouts/_figure.py", line 401, in render
    self.renderer.flush()
  File "/home/kushal/repos/pygfx/pygfx/renderers/wgpu/engine/renderer.py", line 586, in flush
    self._blender.color_view,
    ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Ordered2FragmentBlender' object has no attribute 'color_view'
almarklein commented 2 months ago

We fixed the extra "present-error" for the wgpu-canvas, but I think we should apply a similar trick for the offscreen canvas.