6

I switched from matplotlib to plotly mainly to plot smooth animations in 2D/3D. I want to plot the motion of robots consisting of multiple circles/spheres.

The different body parts of the robot have different sizes and the circles need to represent that accurately. Is there a way in plotly to specify the size of the markers in data units? For example, I want to draw a 5m x 5m section in which circles with a radius of 0.1m are moving along different trajectories.

In matplotlib I know two alternatives. One is to use patches matplotlib.patches.Circle. The second option is to plot the points and scale their markersize correctly by taking the dpi into account (See the answers to this question for matplotlib).

Is there a way in poorly to specify the size of the markers in data units or scale the sizeref attribute correctly?

# Point with radius 2 (approx.)
from plotly.offline import plot
import plotly.graph_objs as go

trace = go.Scatter(x=[4], y=[4],
                   mode='markers',
                   marker={'size': 260, 'sizeref': 1})  # ???

layout = dict(yaxis=dict(range=[0, 10]),
              xaxis=dict(range=[0, 10]))

fig = dict(data=[trace], layout=layout)
plot(fig, image_height=1000, image_width=1000)

A problem with scaling the markersize is that the image is only correct as long as you don't zoom in or out, because the markersize stays constant. Therefore the cleaner approach would be to specify the size of the circles directly in data units.

scleronomic
  • 4,392
  • 1
  • 13
  • 43
  • Forgive me, but I'm still a bit confused after reading through your linked posts and trying to see the direct relevance to your question. I think some more details would be helpful. It seems that your challenge stretches beyond just simply making sure that the relative sizes of your circles are correct. Or am I wrong? And what data units are we talking about here? Centimeters perhaps? So you'd like to make sure that a length of 0,10 on your plot equals ten centimeters? – vestland Oct 23 '19 at 10:56
  • The answers in the linked question show a way to scale the marker_size to data_units for matplotlib. If you plot a 5 x 5 section (say in meter) and draw some points with markersize 0.5, the radius of the circles are normally not 0.5m because the marker_size attribute refers to points/pixels and not to meter. So yes Id like to make sure that a length of 0,10 on my plot equals ten centimeters. And I want it for 3D, and I want to animate my plot. – scleronomic Oct 23 '19 at 12:15
  • To my knowledge there is no 3D animation for plotly at the time being. If the rest is interesting, I'll see if I find the time to take another look at it. – vestland Oct 23 '19 at 12:20
  • 1
    You can listen to zoom (and other) events in JS to get the displayed range (see https://plot.ly/javascript/zoom-events/), and then use these to alter your data. However I'm not sure there's an easy way to do this in Python :( – Barak Itkin Oct 25 '19 at 10:58

1 Answers1

3

Drawing circles is probably your best bet. Updating markersize with each resize would be a bit cumbersome. Here's something you could try for drawing circles

from plotly.offline import plot
import plotly.graph_objects as go

xy = [[4, 4], [1, 5], [2, 2]]
r = 0.1

fig = go.Figure()
kwargs = {'type': 'circle', 'xref': 'x', 'yref': 'y', 'fillcolor': 'black'}
points = [go.layout.Shape(x0=x-r, y0=y-r, x1=x+r, y1=y+r, **kwargs) for x, y in xy]
fig.update_layout(shapes=points)

fig.update_xaxes(range=[0, 10])
fig.update_yaxes(range=[0, 10])
fig.update_layout(width=1000, height=1000)
plot(fig)

Default (1st) and zoomed (2nd) view:

busybear
  • 10,194
  • 1
  • 25
  • 42
  • Thank you. This introduces a bunch of other inconveniences, but it's a solid way of solving exactly the stated problem. – dpq Oct 28 '19 at 06:54