The length of the arrows are not maintained by the 2D quiver plot in figure factory.
See original GitHub issueBug report
Thanks to the Plotly community for this great implementation of 2D quiver plots in the figure factory. The issue is that the length of the arrows are not maintained by the quiver plot.
Bug summary
The length of the arrows in a quiver plot carries relevant information in most applications (wind speed, force field intensity, etc.). This seem to be the case with the quiver plot in figure factory if both axis have the same scale (for example if quiver plot is plotted on a map: x and y coordinates have obviously the same scale). However, as soon as the scales of both axis are different, the apparent length of the arrows is distorted. The barb angle is also affected. This should not be the case.
Code for reproduction
This is an instance of a quiver plot where the scales of both axis are different but where the length of each arrow is intended to be the same (using the norm and an angle to produce u an v).
import plotly.plotly as py
import plotly.figure_factory as ff
import plotly
print(plotly.__version__)
import numpy as np
x,y = np.meshgrid(np.arange(0.5, 3.5, .5), np.arange(0.5, 4.5, .5))
u = x
v = y
angle = np.arctan(v / u)
norm = 0.25
u = norm * np.cos(angle)
v = norm * np.sin(angle)
fig = ff.create_quiver(x, y, u, v, scale = 1)
Actual outcome
The above code produces arrows with apparent lengths changing depending on their angle. This should not be the case.
Expected outcome
This is an instance of the above quiver plot but where the scales of both axis are forced to be the same using specifications on the layout.
x,y = np.meshgrid(np.arange(0.5, 3.5, .5), np.arange(0.5, 4.5, .5))
u = x
v = y
angle = np.arctan(v / u)
norm = 0.25
u = norm * np.cos(angle)
v = norm * np.sin(angle)
fig = ff.create_quiver(x, y, u, v, scale = 1)
fig.layout = go.Layout(
yaxis=dict(
scaleratio = 1,
scaleanchor = "x"
))
It would be nice to have nicely scaled arrows as the above plot but with axis of different scales.
WORKAROUND: To maintain an aspect ratio similar the original plot, we can force a scale ratio different than 1 and apply an inverse transformation on u (or v) to counter the effect of the stretching.
x,y = np.meshgrid(np.arange(0.5, 3.5, .5), np.arange(0.5, 4.5, .5))
u = x
v = y
angle = np.arctan(v / u)
norm = 0.25
scale_ratio = 0.5
u = norm * np.cos(angle) * scale_ratio
v = norm * np.sin(angle)
fig = ff.create_quiver(x, y, u, v, scale = 1)
fig.layout = go.Layout(
yaxis=dict(
scaleratio = scale_ratio,
scaleanchor = "x"
))
This workaround is not perfect though. Despite the fact that the length of the arrows are maintained, the barbs of the arrows are still distorted and they don’t look good.
Plotly version
- Operating system: Ubuntu 16.04 Bash on Windows10
- Plotly version: 3.2.1
- Python version: 3.5.6 plotly installed from pip
Issue Analytics
- State:
- Created 5 years ago
- Comments:9 (9 by maintainers)
I like the callback function approach a lot. I will look into it. Thanks!
Let’s close this issue as your initial solution was merged and included in version 3.3.0. Why don’t you open a new issue to discuss the
FigureWidget
approach when you have time if you’re still interested in perusing that. Thanks!