Skip to content
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

Add washing machine to Axes3D #19937

Closed
wants to merge 1 commit into from

Conversation

r-barnes
Copy link

@r-barnes r-barnes commented Apr 11, 2021

PR Summary

Seeing the structure of 3D plots can be challenging if the plots are stationary. This PR adds a "washing machine" perturbation that gently and continuously moves the 3D axes to help reveal the 3d structure of the data.

A movie of this in action is here (pause the video to see the difficulty of interpreting the data sans the animation) and a gif is here.

The animation is toggled by pressing the "z" key.

This PR doesn't (yet!) include all the features of a good PR as I expect there might be some discussion regarding how best to execute this feature.

Note that the motion could also be made smoother and I haven't figured out how to pin the motion to, say, the back corner of the axes, which might provide better depth cues than the current motion which, I think, is pinned more to the center of the axes cube.

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • New features are documented, with examples if plot related.
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and run flake8 --docstring-convention=all).
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).

@story645
Copy link
Member

Hi, any chance you can convert the movie into a gif that you can then post here? At least on my phone, the link redirects to a download.

@r-barnes
Copy link
Author

Sure, @story645.

Still image:

Still image

With the washing machine:

Washing machine effect

Also available here.

@r-barnes
Copy link
Author

Some studies relating motion to 3D data comprehension are here and here. I'm looking for others.

@timhoffm
Copy link
Member

I like the idea of adding motion to help understand 3D information. Some comments/suggestions/information:

  • Our current 3D camera view model is limited to the degrees azimuth and elevation, which are aound the center of the view. You cannot rotate around a back-corner.
  • More generally, this could be any closed path in the (azimuth, elevation)-space; e.g. I imagine that full azimuth rotation can also be quite desireable.
  • A similar effect can be achieved with animations (see example below). Compared to the current approach this has the advantage that (i) you can also save the animation to file (ii) you can use it in juypyter notebooks. On the downside, AFAIK we currently don't have a way to pause animations in a GUI window, but that could be added.
  • I'm not clear if this needs additional API or if an example would be enough.

Example with animation:

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


# Fixing random state for reproducibility
np.random.seed(19680801)


def random_walk(length):
    start_pos = np.random.random(3)
    steps = np.random.uniform(-0.05, 0.05, size=(length, 3))
    walk = start_pos + np.cumsum(steps, axis=0)
    return walk
    

def update_view(frame):
    azim = frame * (360/72)
    ax.view_init(azim=azim)


fig = plt.figure()
ax = fig.add_subplot(projection="3d")

for _ in range(50):
    ax.plot(*random_walk(25).T)

ax.set(xlim3d=(0, 1), ylim3d=(0, 1), zlim3d=(0, 1))

ani = animation.FuncAnimation(
    fig, update_view, 72, interval=50)
plt.show()

Use anim.save('test.gif') for saving instead or for embedding into jupyter notebooks:

from IPython.display import HTML
HTML(ani.to_jshtml(fps=20))

For illustration: (The written gif still has a clipping problem, that's not present in the other output formats, but that's an unrelated issue)
test

@r-barnes
Copy link
Author

Thanks, @timhoffm .

More generally, this could be any closed path in the (azimuth, elevation)-space

In the push I just made, I've switched to using a sin-cos combo which I think produces a nicer view.

A similar effect can be achieved with animations (see example below).

I've seen that; thank you for providing an example. The downside to relying solely on the existing animation framework is that you have to either have an example bookmarked or type everything out each time you need this. Having it built in means I can create 3d plots for quick analysis without having to think too much about this aspect of visualization. Later, if I wanted something smoother or reproducible, I would build an animation. So I think there are distinct use cases here.

@timhoffm
Copy link
Member

We could certainly come up with an API that does not need much typing, e.g. ax.animate_view('washingmachine') / ax.animate_view('azim_rotation').

Or with more degrees of freedom: ax.animate_view(ViewAnimation(elev=30, azim=np.arange(0, 360, 73), interval=100))

@r-barnes
Copy link
Author

But, if I understand correctly, the animation approach you propose would run continuously in a way that would prevent or interfere with a user doing custom zooms, rotations, or freezes?

@anntzer
Copy link
Contributor

anntzer commented Apr 12, 2021

@timhoffm Side point: I can't repro the gif clipping failure, but do you want to open a separate issue for that?

@tacaswell tacaswell added this to the v3.5.0 milestone Apr 13, 2021
@tacaswell
Copy link
Member

👍 This is a cool idea!

@r-barnes
Copy link
Author

I've moved the rotation keys to "z" and "x". "z" does a washing machine and "x" performs a continuous azimuthal rotation.

@jklymak
Copy link
Member

jklymak commented Apr 15, 2021

@r-barnes We discussed this one on the dev call this week. For now, we think this would be best as a third-party package. We are updating our third party package page, but in the meantime you would be welcome to link you package on our third-party page.

Thanks for the cool idea!

@jklymak
Copy link
Member

jklymak commented May 15, 2021

BTW the third-party page is https://github.com/matplotlib/mpl-third-party. Thanks for the interesting idea!

@jklymak jklymak closed this May 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants