Pyplot Interactive Zooming - python

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.

Related

How to make plots customizable in python

I have two issues with my python plot that would be grateful if anyone could help me with:
1- I wonder if it is possible in python to have the option for the plots after display to add horizontal or vertical lines, so that these new lines could be added, moved or deleted without the need to run the code again.
to say it more clearly, I am looking for additional features that adding them does not need to change the code and they only enable me to manually draw on the already plotted image.
2- I want to plot a very large image in the real size, So that I need to add the horizontal and vertical slide bars to be able to scroll up/down or left/right in the plot?
I need to combine these two ability for my project, can someone help me with that?
1- You can't physically draw on it, but you can make a plot in matplotlib interactive as follows:
import matplotlib.pyplot as plt
plt.ion() # turns on interactive mode
fig = plt.figure()
ax = fig.add_subplot()
plt.ylim(-10, 10)
plt.xlim(0, 10)
while True:
plt.axhline(float(input("number")))
fig.canvas.draw()
fig.canvas.flush_events() # draws
This program allows you to create horizontal lines based on user input.
I think you can solve 2 with tkinter, but that would be pretty difficult. There might also an easier way. See this stack overflow question for an example of an interactive plot in tkinter. I believe this plot can be made bigger and scrollable, but I am not sure.

enlarging the figure in the pop-out window in matplotlib

How to enlarge a figure inside the pop-out window? I use the following code to generate my figure:
self._fig = plt.figure()
#self._fig = plt.figure(figsize=(2,1)) # tried this, didn't work, only change the size of the pop-out window, but now the figure itself
ax1 = self._fig.add_subplot(211,projection='3d')
# some code for plotting the lines and drawing the spherical surfaces, which is not shown here
ax1.set_xlim(-6,6)
ax1.set_ylim(-6,6)
ax1.set_zlim(-15,15)
ax1.set_aspect(2.5, 'box') # the axis limit and aspect limit is chosen so that the whole figure has the same scale in all directions
#ax1.view_init(elev=90, azim=0)
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')
ax1.set_zlabel('Z-axis')
ax1.grid(True)
You can see that there is lot of unused space in the pop-out window, and the figure looks really small. I want to maximize the size of the figure so that it fills the whole pop-out window. Now even if I manually enlarge the pop-out window, the figure still looks the same.
I tried varying the axis limits, but it doesn't seem to work. I tried setting the
figsize in the first line, but it only changes the size of the pop-out window, but the figure itself.
Another problem is that I want to change the 'camera-view' of the figure so that the z-axis (the lone axis) is horizontal. Again, I tried a range of different values in ax.view_init, but I can't get the view I want. I only allows me rotate around the z-axis, while what I need to do is to rotate around x or y-axis by 90deg.
Try calling plt.tight_layout()
before you call plt.show()

How to Zoom with Axes3D in Matplotlib

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.

matplotlib how is a figure structured?

So I'm trying to understand how a figure is structured. My understanding is the following:
you have a canvas (if you've got a gui or something similar), a figure, and axes
you add the axes to the figure, and the figure to the canvas.
The plot is held by the axes, so for example:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1, 2], [1, 4])
fig.show()
I would expect would create a figure however I just get a blank window... Also, it seems canvas is not needed at all?
any help appreciated thank you!
here it says the above code should work... or has a similar example
https://github.com/thehackerwithin/PyTrieste/wiki/Python7-MatPlotLib
You shouldn't be poking at the canvas unless you really know what you are doing (and are embedding mpl into another program). pyplot has a bunch of nice tools that takes care of most of the set up for you.
There is a separation between the user layer (figures, axes, artists, and such) and the rendering layer (canvas, renderer, and such). The first layer is user facing and should be machine independent. The second layer is machine specific, but should expose none of that to
the user.
There are a varity of 'backends' that take care of the translation between the two layers (by providing sub-classes of canvas and such). There are interactive backends (QtAgg, GtkAgg, TkAgg,...) which include all the hooks into a gui toolkit to provide nice windows and non-interactive backend (PS, pdf, ...) that only save files.
figures hold axes which hold artists (and axis). Those classes will talk to the rendering layer, but you (for the most part) do not need to worry about exactly how.

Getting matplotlib plots to refresh on mouse focus

I am using matplotlib with interactive mode on and am performing a computation, say an optimization with many steps where I plot the intermediate results at each step for debugging purposes. These plots often fill the screen and overlap to a large extent.
My problem is that during the calculation, figures that are partially or fully occluded don't refresh when I click on them. They are just a blank grey.
I would like to force a redraw if necessary when I click on a figure, otherwise it is not useful to display it. Currently, I insert pdb.set_trace()'s in the code so I can stop and click on all the figures to see what is going on
Is there a way to force matplotlib to redraw a figure whenever it gains mouse focus or is resized, even while it is busy doing something else?
Something like this might work for you:
import matplotlib.pyplot as plt
import numpy as np
plt.ion() # or leave this out and run with ipython --pylab
# draw sample data
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot(np.random.rand(10))
class Refresher:
# look for mouse clicks
def __init__(self, fig):
self.canvas = fig.canvas
self.cid = fig.canvas.mpl_connect('button_press_event', self.onclick)
# when there is a mouse click, redraw the graph
def onclick(self, event):
self.canvas.draw()
# remove sample data from graph and plot new data. Graph will still display original trace
line.remove()
ax.plot([1,10],[1,10])
# connect the figure of interest to the event handler
refresher = Refresher(fig)
plt.show()
This will redraw the figure whenever you click on the graph.
You can also experiment with other event handling like
ResizeEvent - figure canvas is resized
LocationEvent - mouse enters a new figure
check more out here:
Have you tried to call plt.figure(fig.number) before plotting on figure fig and plt.show() after plotting a figure? It should update all the figures.

Categories