widgetti / solara

A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
https://solara.dev
MIT License
1.9k stars 141 forks source link

plotly figure example: error on moving shapes #509

Open swelborn opened 8 months ago

swelborn commented 8 months ago

The plotly figure works when drawing shapes, but fails with the following error when moving them or resizing them. Using code directly from example source.

ERROR:    Uncaught exception: Traceback (most recent call last):
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 238, in m
    return(method(self, *args, **kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 757, in _handle_msg
    self.set_state(state)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 621, in set_state
    with self._lock_property(**sync_data), self.hold_trait_notifications():
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/contextlib.py", line 144, in __exit__
    next(self.gen)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/reacton/core.py", line 393, in hold_trait_notifications_extra
    with rc, hold_trait_notifications(*args, **kwargs):
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/contextlib.py", line 144, in __exit__
    next(self.gen)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/traitlets/traitlets.py", line 1510, in hold_trait_notifications
    self.notify_change(change)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 687, in notify_change
    super(Widget, self).notify_change(change)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/traitlets/traitlets.py", line 1525, in notify_change
    return self._notify_observers(change)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/traitlets/traitlets.py", line 1568, in _notify_observers
    c(event)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/plotly/basewidget.py", line 635, in _handler_js2py_relayout
    self.plotly_relayout(relayout_data=relayout_data, source_view_id=source_view_id)
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/plotly/basedatatypes.py", line 2610, in plotly_relayout
    relayout_changes = self._perform_plotly_relayout(relayout_data)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/swelborn/miniconda3/envs/tomopyui-dev/lib/python3.11/site-packages/plotly/basedatatypes.py", line 2646, in _perform_plotly_relayout
    raise ValueError(
ValueError:
Invalid property path 'shapes[0].x0' for layout
maartenbreddels commented 8 months ago

Hi,

what do you mean by moving or resizing, how do I reproduce this?

Regard,

Maarten

swelborn commented 8 months ago

Try clicking on a shape to select it, then moving it/resizing it.

maartenbreddels commented 8 months ago

On https://solara.dev/examples/visualization/annotator ? Because I cannot move them. Can you show a screencast?

swelborn commented 8 months ago

https://github.com/widgetti/solara/assets/55868530/50ae9c7f-e113-41b0-938f-05ed966a172a

You have to double-click on the edge of the box to select

maartenbreddels commented 8 months ago

I've managed to reproduce it, and the solution seems to be that we should pass 'shapes' back to Layout. My diff is:

diff --git a/solara/website/pages/examples/visualization/annotator.py b/solar>
index d2037f95..bd42b4ab 100644
--- a/solara/website/pages/examples/visualization/annotator.py
+++ b/solara/website/pages/examples/visualization/annotator.py
@@ -37,6 +37,7 @@ def Page():
             return

         relayout_data = data["relayout_data"]
+        print(data)

         if "shapes" in relayout_data:
             shapes.value = relayout_data["shapes"]
@@ -48,6 +49,7 @@ def Page():
             width=600,
             height=600,
             dragmode="drawrect",
+            shapes=shapes.value,
             modebar={
                 "add": [
                     "drawclosedpath",

But, if I first draw, and the drag the shape, my output is:

{'relayout_data': {'shapes': [{'editable': True, 'xref': 'x', 'yref': 'y', 'layer': 'above', 'opacity': 1, 'line': {'color': '#444', 'width': 4, 'dash': 'solid'}, 'fillcolor': 'rgba(0,0,0,0)', 'fillrule': 'evenodd', 'type': 'rect', 'x0': 1.296211797540838, 'y0': 2.5936511811755953, 'x1': 2.918939070268111, 'y1': 0.6650797526041666}]}, 'source_view_id': 'a612dc'}
{'relayout_data': {'shapes[0].x0': 1.2961590909090912, 'shapes[0].x1': 2.9188863636363642, 'shapes[0].y0': 2.5936904761904764, 'shapes[0].y1': 0.8436904761904762}, 'source_view_id': 'a612dc'}
{'relayout_data': {'shapes[0].x0': 1.2961590909090912, 'shapes[0].x1': 2.9188863636363642, 'shapes[0].y0': 2.5936904761904764, 'shapes[0].y1': 0.9389285714285714}, 'source_view_id': 'a612dc'}
{'relayout_data': {'shapes[0].x0': 1.2961590909090912, 'shapes[0].x1': 2.7120681818181827, 'shapes[0].y0': 2.5936904761904764, 'shapes[0].y1': 1.1532142857142857}, 'source_view_id': 'a612dc'}
{'relayout_data': {'shapes[0].x0': 1.2961590909090912, 'shapes[0].x1': 2.3620681818181826, 'shapes[0].y0': 2.5936904761904764, 'shapes[0].y1': 1.3913095238095239}, 'source_view_id': 'a612dc'}
{'relayout_data': {'shapes[0].x0': 1.2961590909090912, 'shapes[0].x1': 1.773431818181819, 'shapes[0].y0': 2.5936904761904764, 'shapes[0].y1': 1.760357142857143}, 'source_view_id': 'a612dc'}

This seem to be related to the error you got above (Invalid property path 'shapes[0].x0' for layout ) I don't know enough about plotly to understand what is going on, maybe you and/or @itepifanio (who added the example) can take a look?

cheers,

Maarten

itepifanio commented 8 months ago

@maartenbreddels @swelborn unfortunately this is not a problem from our side. I opened a related issue at Plotly repo previously.

In the image annotator I built using this component I was rerendering it when capturing the relayout events, to avoid this changes. It's not that efficient, but it was enough to continue the POC development.