Skip to content

Easier vectorized line segments and arrows  #19705

@vsbuffalo

Description

@vsbuffalo

Per this discussion on Twitter, the matplotlib account suggested we create a feature request for easier arrows. In thinking about how this could be addressed, I think it ties in with another frustration I have with matplotlib: drawing lots of line segments and both could be tackled with the same new function.

Problem

Visually, arrows can be used for a lot of different purposes. plt.annotate() is great for pointing to a feature and labeling it with text, but is not a solid solution for data-to-data pointing because the arrow tips don't fall in the center of the points, e.g.see this example.

plt.arrow() seems like the right solution. However, for general purposes, it has two main shortcomings. First, the scaling of the arrowhead is not automatic, so for certain scales of data the arrowheads look bizarre by default, and the arguments are not vectorized.

# it looks fine if we don't divide by 100, but if we do, the scaling is way off
x0 = np.random.uniform(0, 1, 5) / 100
y0 = np.repeat(0, 5)

dx = np.random.normal(0, 0.1, 5) / 100
dy = np.repeat(1, 5)

for i in range(5):
    plt.arrow(x0[i], y0[i], dx[i], dy[i])

Screen Shot 2021-03-14 at 3 35 21 PM

Second, as the example shows, the arguments x, y, dx, and dy are not vectorized and explicit looping is required. This relates to another section of the API that's undesirably complex in my view: to draw lots of line segments, one needs to use a LineCollection and use ax.add_collection().

Proposed Solution

Matplotlib could solve both of these issues with a new ax.segments() method. This would take xto, xfrom, yto, and yfrom arguments, and ideally a vector of colors or labels too, and then plot the line segments. Then, one could pass an arrowstyle argument too, which would turn this into a collection of line segments with arrow ends. Also, I think in general it would be easier if the API used to and from coordinates rather than from and dx, dy coordinates. Finally, the default should be that the arrows are lines, rather than filled rectangles as with plt.arrow(), which create visually odd thin-width arrow bodies depending on the angle is steep between the two and from points.

Metadata

Metadata

Assignees

No one assigned

    Labels

    New featurestatus: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.status: inactiveMarked by the “Stale” Github Actiontopic: arrow

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions