Skip to content

Feature request: set_XY in quiver plots #11790

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
t-makaro opened this issue Jul 28, 2018 · 17 comments
Closed

Feature request: set_XY in quiver plots #11790

t-makaro opened this issue Jul 28, 2018 · 17 comments
Labels
New feature status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action

Comments

@t-makaro
Copy link
Contributor

Quiver plots currently have a set_UVC method which lets one animate the direction that the arrows point. Unfortunately, they do not have a set_XY, so one cannot animate the location of the arrows.

This limitation makes is hard to make things like: (An animation of elliptical polarization)
polarization
without resorting to simply clearing the axis, and redrawing everything on every frame. This annoyance get's compounded with even more complex animations.

@jklymak
Copy link
Member

jklymak commented Jul 28, 2018

Seems a reasonable addition. OTOH, I wouldn't necessarily have thought quiver was the right method for just drawing arrows. I think the reason that this hasn't been added before is that most quiver plots are thought of as mapping a field of vectors, and the field locations don't usually change. But there is no reason they couldn't.

@t-makaro
Copy link
Contributor Author

I can think of lots of uses for something like this. For example, lets say I have a vector field and I want to apply a rotation to it. It would be nice to see the vector field actually rotate, and not just the arrows changing direction. I'll admit that changing the location of the arrows is more niche than setting the direction, so that's why I think a set_XY would be better than a set_XYUVC (that and backwards compatibility). When needing to animate a large number of arrows, ax.annotate isn't great to use.

For api consistency, we'd probably want a set_XY for barb plots too.

@dopplershift
Copy link
Contributor

My gut says there's probably some implementation details that make this more than trivial, but I'd be willing to merge the work of someone else doing this. 😁

@tacaswell tacaswell added this to the v3.1 milestone Jul 31, 2018
@jklymak jklymak modified the milestones: v3.1.0, unassigned Feb 11, 2019
@fruchart
Copy link

I don't know if this is a good method, but it can be done with qu.set_offsets(np.array([X.flatten(), Y.flatten()]).T) where qu is the matplotlib.quiver.Quiver object. It is described e.g. there.

@daniel-cr
Copy link

This is kind of related too. If you increase the number of arrows with set_offsets and then try to update the (U,V) with set_UVC you will get a ValueError even if both are the same dimension.
The total number of arrows doesn't update as the Quiver class doesn't have a proper set_offsets function.

The following code procs the error in 3.3.2

import matplotlib.pyplot as plt
import numpy as np

X, Y = np.random.rand(10, 2).T
U, V = np.random.rand(10, 2).T

fig, ax = plt.subplots()
Q = ax.quiver(X, Y, U, V)

X, Y = np.random.rand(11, 2).T
Q.set_offsets(np.array([X, Y]).T)

U, V = np.random.rand(11, 2).T
Q.set_UVC(U, V)

plt.show()

@timhoffm
Copy link
Member

timhoffm commented Nov 1, 2020

@daniel-cr Changing the number of arrows is currently not supported consistently (we should proabably already fail on set_offsets(). The problem is that it is hard to maintain a valid state. X, Y, U, V, C need to have the same size, and also you have parameters like color, that can be one element per arrow.

@theovincent
Copy link

I know it is not the best way of doing it but if you really want to change the number of arrows, matplotlib version 3.1.3 allows you to do it :)

@yasser-h-khalil
Copy link

@thevincent could you please show me how it is done?

@theovincent
Copy link

theovincent commented Dec 3, 2020

@thevincent could you please show me how it is done?

@yasser-h-khalil here is a simple example with matplotlib 3.1.3 :

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# -- Input -- #
positions = [
    np.array([[0, 0], [0, 1], [1, 0]]),  # time = 0
    np.array([[0.1, 0], [0, 1.1]]),  # time = 1
    np.array([[0.2, 0], [0, 1.2], [1.1, 0]]),  # time = 2
]
angles = [
    np.pi * np.array([10, 20, 30]) / 180,  # time = 0
    np.pi * np.array([13, 23]) / 180,  # time = 1
    np.pi * np.array([15, 25, 33]) / 180,  # time = 2
]


# -- Quiver -- #
fig, ax = plt.subplots()
ax.set_xlim([-1, 2])
ax.set_ylim([-1, 2])

players = ax.quiver(positions[0][:, 0], positions[0][:, 1], np.cos(angles[0]), np.sin(angles[0]), scale=20)


def animate(idx_timestamp):
    players.set_offsets(positions[idx_timestamp])
    players.set_UVC(np.cos(angles[idx_timestamp]), np.sin(angles[idx_timestamp]))

    return (players,)


anim = FuncAnimation(fig, animate, frames=len(positions), blit=True, interval=1000, repeat=False)

anim.save("example.mp4", fps=1, dpi=150)
plt.close()

Which produces this following :

example

@yasser-h-khalil
Copy link

Thank you this works. It seems this feature is available only on version 3.1.3, as I tried on 3.3.2 and it failed.
One more question if you don't mind. I have been trying to update the color array for each arrow using set_UVC(U, V,C) but it fails.

I had it like this:

Q = ax.quiver(X, Y, U, V, color=color)
color = np.array(['b','b','r','r','g','g','m','m','y','y'])

...

Q.set_UVC(U, V,color)

Any suggestions. Thanks.

@HaaLeo
Copy link

HaaLeo commented Dec 3, 2020

I would love to do this in matplotlib 3.3.3, too.

@theovincent
Copy link

theovincent commented Dec 3, 2020

One more question if you don't mind. I have been trying to update the color array for each arrow using set_UVC(U, V,C) but it fails.

@yasser-h-khalil, it should work if you use :
players.set_facecolors(colors[idx_timestamp]) # with len(colors[idx_timestamp]) = len(positions[idx_timestamp])

@jklymak
Copy link
Member

jklymak commented Dec 3, 2020

Just to re-iterate - I'm sure we would accept a PR for setting set_xy. I'm not sure we would consider changing the number of quivers a robust feature, but if there were a separate PR that had a clean API, I imagine we could do so. As @timhoffm says, there is a lot of state to carry around and sync up.

I will also re-iterate that this is all likely better done with arrow calls if you are just dealing with a finite number of points that are moving around.

@yasser-h-khalil
Copy link

One more question if you don't mind. I have been trying to update the color array for each arrow using set_UVC(U, V,C) but it fails.

@yasser-h-khalil, it should work if you use :
players.set_facecolors(colors[idx_timestamp]) # with len(colors[idx_timestamp]) = len(positions[idx_timestamp])

True. It works. However, I noticed it is a slow command.
I figured out that the color array needs to be float to be accepted by set_UVC. But I still didn't figure out what are the type of those float numbers. Like what float number reflects what color.

Thanks.

@jklymak
Copy link
Member

jklymak commented Dec 3, 2020

@yasser-h-khalil Please take user-help to discourse.matplotlib.org. Thanks!

@ianhi
Copy link
Contributor

ianhi commented Feb 5, 2022

See #22407 for a possible set_data that allows changing the number of arrows.

@story645 story645 modified the milestones: unassigned, needs sorting Oct 6, 2022
@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Oct 11, 2023
@github-actions github-actions bot added the status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. label Nov 10, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New feature status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action
Projects
None yet
Development

Successfully merging a pull request may close this issue.