Skip to content

Feature request: set_XY in quiver plots #11790

Closed as not planned
Closed as not planned

Description

@t-makaro

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.

Activity

  1. jklymak commented on Jul 28, 2018

    @jklymak
    Member

    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.

  2. t-makaro commented on Jul 28, 2018

    @t-makaro
    ContributorAuthor

    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.

  3. dopplershift commented on Jul 31, 2018

    @dopplershift
    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. 😁

  4. added this to the v3.1 milestone on Jul 31, 2018
  5. modified the milestones: v3.1.0, on Feb 11, 2019
  6. fruchart commented on Jun 28, 2019

    @fruchart

    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.

  7. daniel-cr commented on Oct 18, 2020

    @daniel-cr

    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()
    
  8. timhoffm commented on Nov 1, 2020

    @timhoffm
    Member

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

  9. theovincent commented on Nov 16, 2020

    @theovincent

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

  10. yasser-h-khalil commented on Dec 2, 2020

    @yasser-h-khalil

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

  11. theovincent commented on Dec 3, 2020

    @theovincent

    @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

  12. yasser-h-khalil commented on Dec 3, 2020

    @yasser-h-khalil

    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.

  13. HaaLeo commented on Dec 3, 2020

    @HaaLeo

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

  14. theovincent commented on Dec 3, 2020

    @theovincent

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

  15. jklymak commented on Dec 3, 2020

    @jklymak
    Member

    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.

  16. yasser-h-khalil commented on Dec 3, 2020

    @yasser-h-khalil

    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.

  17. jklymak commented on Dec 3, 2020

    @jklymak
    Member

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

  18. ianhi commented on Feb 5, 2022

    @ianhi
    Contributor

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

  19. modified the milestones: , needs sorting on Oct 6, 2022
  20. github-actions commented on Oct 11, 2023

    @github-actions

    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!

  21. added
    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.
    on Nov 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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 Action

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions