K3D-tools / K3D-jupyter

K3D lets you create 3D plots backed by WebGL with high-level API (surfaces, isosurfaces, voxels, mesh, cloud points, vtk objects, volume renderer, colormaps, etc). The primary aim of K3D-jupyter is to be easy for use as stand alone package like matplotlib, but also to allow interoperation with existing libraries as VTK.
MIT License
916 stars 123 forks source link

dict-based animations won't update when headless #451

Open spanag opened 3 months ago

spanag commented 3 months ago

What I Did

import k3d
data = {'0':[0,0,.5],'1':[0,0,-.5]}
plot = k3d.plot()
works = False # toggle me
if works: points = k3d.points(positions=data['0'],point_size=1); plot += points
else: points = k3d.points(positions=data,point_size=1); plot += points
plot.display(); plot.start_auto_play()
from k3d.headless import k3d_remote, get_headless_driver
frames = []
try:
    headless = k3d_remote(plot, get_headless_driver(), width=200, height=200)
    headless.sync(hold_until_refreshed=True)
    headless.camera_reset(1)
    for i in range(2):
        if works: points.positions = data[str(i)]
        else: plot.time = i
        headless.sync()
        frames.append(headless.get_screenshot())
finally:
    headless.close()
from IPython.display import display, Image
display(*[Image(data=x) for x in frames])

The animation runs fine on the browser, but the captured snapshots are identical (same as the first frame) although they are captured for different points in time. If position is set explicitly for each frame with works = True , then rendering works as intended.

Web console log / python logs

When works = False, I get the following message on each frame, which however doesn't stop execution:

[2024-03-11 19:03:57,965] ERROR in app: Exception on / [POST]
Traceback (most recent call last):
  File "/opt/conda/lib/python3.11/site-packages/k3d/headless.py", line 70, in generate
    sync = (o[p] != self.synced_objects[o.id][p]).any()
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.11/site-packages/k3d/headless.py", line 73, in generate
    sync = o[p].shape != self.synced_objects[o.id][p].shape
           ^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'shape'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.11/site-packages/flask/app.py", line 1463, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/conda/lib/python3.11/site-packages/flask/app.py", line 872, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/conda/lib/python3.11/site-packages/flask/app.py", line 870, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/conda/lib/python3.11/site-packages/flask/app.py", line 855, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/conda/lib/python3.11/site-packages/k3d/headless.py", line 75, in generate
    sync = o[p] != self.synced_objects[o.id][p]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()