How to Zoom with Axes3D in Matplotlib - python

I am generating a 3D plot using matplotlib. I want to be able to zoom in on areas of interest. Currently, I am able to pan but not zoom. Looking at the mplot3d API, I learned about can_pan():
Return True if this axes supports the pan/zoom button functionality.
3D axes objects do not use the pan/zoom button.
and can_zoom():
Return True if this axes supports the zoom box button functionality.
3D axes objects do not use the zoom box button.
They both return False (I think can_pan returns False because the axes cannot pan AND zoom both but maybe I am reading the API wrong).
Is there a way to enable Zoom? The API indicates it does not use the buttons. Is there some way to enable zoom or set it so can_pan() and can_zoom() return True?
Here is a snippet of the code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
data = np.genfromtxt('data_file.txt')
fig1 = plt.figure()
ax1 = fig1.gca(projection='3d')
ax1.scatter(data[:,0],data[:,1],data[:,2], c='r', marker='.')
plt.show()
ax1.can_zoom()
>>> False
ax1.can_pan()
>>> False
I am using Python 2.7 on an Ubuntu 14.04 64bit desktop version machine with matplotlib installed from the default repositories (I can look the versions up if that is pertinent).

Actually #tcaswell is correct that this functionality doesn't exist and so it returns false. Have you tried zoom-to-rectangle button on the plot window? That works perfectly. If you haven't yet, then refer to the matplotlib instructions on Interactive Navigation.
You can zoom in using two ways:
Clicking on pan/zoom button:
Press the right mouse button to zoom, dragging it to a new position. The x axis will be zoomed in proportionate to the rightward movement and zoomed out proportionate to the leftward movement.
Clicking on zoom-to-rectangle button:
Put your mouse somewhere over and axes and press the left mouse button. Drag the mouse while holding the button to a new location and release.

Instead of zoom functionality, you can control the limit of the axis like
RADIUS = 1.0 # Control this value.
ax1.set_xlim3d(-RADIUS / 2, RADIUS / 2)
ax1.set_zlim3d(-RADIUS / 2, RADIUS / 2)
ax1.set_ylim3d(-RADIUS / 2, RADIUS / 2)
and you see your data in closer view if you define RADIUS variable smaller. In this example you can zoom into and zoom out from the origin.
You can optionally choose other focus point although you need to calculate the appropriate limit to achieve the desired view. Hope this helps.
I'm not sure it works in python2 because I have no such environment.

You could drag scroll wheel on mouse to zoom as well.

Related

Matplotlib interactive zoom on a mac laptop, where control is used for right click

In a matplotlib figure window, I can press the little "4 arrows" button to pan and zoom the plot. At some point, matplotlib introduced the feature where the control key can be used to lock the aspect ratio. Unfortunately, on my Mac laptop, control is used to enable right-clock functionality. So, if I want to zoom the plot (right click), then I need to hold down the control key, which locks the aspect ratio of the zoom. Generally, I don't want the aspect ratio locked.
I found that I can hold down both control+x or control+x and move the mouse to zoom in just the x or y directions. However, I prefered the old behavior where I can just hold down control and zoom in both z and y simultaneously. Any idea for how to restore the previous behavior?
There is some discussion how how this works under "The Pan/Zoom button" here: https://matplotlib.org/3.2.2/users/navigation_toolbar.html

Disable displaying coordinate in matplotlib plot

I'm now embedding matplotlib plot in a simple GUI. During the customization of the plot, I found some displaying issues occurred when I added tool bar under the plot using NavigationToolbar2TkAgg. Now I want to disable displaying coordinate at right side of the bottom of plot when mouse moves around the plot, if we add tool bars at the left side of the bottom. Any idea about this?
Thanks in advance.
Update:
For a figure simply drawn by plt.plot(x,y), the coordinates are displayed at left side of the bottom along with mouse moving as tool bars (like "home", "zoom" etc.) are listed at the top by default. It will be much clearer to view the screen shot at google drive here and I highlighted the coordinates in yellow, which one can find at the bottom left of the image. Thanks GWW and jgysland for reminding me.
You want the opposite of matplotlib values under cursor, but the solution is the same, you need to over-write the format_coord attribute on the Axes object.
ax.format_coord = lambda x, y: ''
should do the trick where ax is a reference to the axes object you care about.
Another option is to sub-class NavigationToolbar2TkAgg and make the set_message function a no-op
class my_toolbar(NavigationToolbar2TkAgg):
def set_message(self, msg):
pass

Changing center of rotation in a Matplotlib 3D plot

I have a 3D line plot in matplotlib, created using the following code:
def view(self):
from mpl_toolkits.mplot3d import Axes3D #noqa
import matplotlib.pyplot as plt
ax = plt.figure().gca(projection='3d')
history = np.array(self.position_history)
x, y ,z = history[:, 0], history[:, 1], history[:, 2]
ax.plot(x, y, z)
plt.show()
Here history is an Mx3 array of points. This works fine and pops up a plot as expected. I am able to click and drag to modify the azimuth and elevation interactively. I am able to zoom by right-clicking and dragging.
However I am wondering if it is possible to modify the center point of the pan and zoom? I would like to zoom into the top-right, and then pan around with the top right as my center of rotation. If you have ever used solidworks or another CAD program, this is the behavior I am after. Is this doable? If not interactively, can I do it programmatically?
And finally, if none of this is possible in matplotlib, is there another library that can accomplish what I want?
I have also run into trouble in the past in terms of customizing mplot3d, rather unsuccessfully..
And finally, if none of this is possible in matplotlib, is there another library that can accomplish what I want?
you can do this with mayavi
here is a relevant stackoverflow answer for customizing how you interact with your plot
there are also various useful tips and tricks for animating in general and for using mayavi
(apologies if this isn't useful)
Not sure this will do what you need but you can define the center when you first plot. Here, "c_x" is the center of rotation on the x axis and the -/+ 200 defines the axis to be 200 units in both direction. Likewise for y and z.
If you had the user choose the center before plotting, that could work as a crude work around.
http://matplotlib.org/api/axes_api.html?highlight=set_xbound#matplotlib.axes.Axes.set_xbound
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.autoscale(enable=False,axis='both') #you will need this line to change the Z-axis
ax.set_xbound(c_x-200, c_x+200)
ax.set_ybound(c_y-200, c_y+200)
ax.set_zbound(c_z-200, c_z+200)

Pyplot Interactive Zooming

I want to display an image that is zoomed in when first shown, but still has the ability to zoom out to the full scale using the interactive "Reset original view" button in the figure toolbar. Cropping is completely unacceptable. Using plt.axis([x0, x1, y0, y1]) does allow panning but the interactive window will not reset to full scale.
Is there a way to trigger the plot to zoom or solve this issue another way?
A way to do this is:
fig, ax = plt.subplots(1, 1)
ax.imshow(np.random.rand(20, 20)
fig.canvas.toolbar.push_current() # save the 'un zoomed' view to stack
ax.set_xlim([5, 10])
ax.set_ylim([5, 10])
fig.canvas.toolbar.push_current() # save 'zoomed' view to stack
I am not sure how private push_current is considered and as I said in the comments this is being refactored for 1.5 (https://github.com/matplotlib/matplotlib/wiki/Mep22).
See https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backend_bases.py#L2600 for how pan/zoom are implemented. The reason there isn't a 'zoom_window' command is for static images, you just use set_*lim.

Matplotlib zooming work in conjunction with wxPython ScrolledWindow

I've got a Matplotlib canvas (FigureCanvasWxAgg) that I'm displaying inside of a wx.ScrolledWindow. The problem is that I'd like to have the default zooming and panning functionality of Matplotlib work in conjunction with the ScrolledWindow, so that when the user zooms the image within the canvas, the ScrolledWindow should become larger to accommodate for the zooming (scrollbars become smaller). Similarly for panning, I'd like the default matplotlib panning tool to work in conjunction with our ScrolledWindow, so that when the user pans the image on the canvas, the ScrolledWindow's scrollbars should move accordingly.
I've been searching for a while now and have not seen anyone even mention if this is possible. Could anyone point me in the right direction?
Thank you for any help/tips.
The problem is that the default Zoom and Pan don't resize the figure, they just change the limits and redraw the plot.
What you want is the Zoom to resize (keeping the same limits) and the Pan to work as in a normal Scrolled window. I have never tried this, fig.set_size_inches(w,h) should do the trick.

Categories