Skip to content

The length of the arrows are not maintained by the 2D quiver plot in figure factory. #1187

Closed
@dabana

Description

@dabana

Bug 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.

fig1

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"
    ))

fig2

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"
    ))

fig3

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions