enlarging the figure in the pop-out window in matplotlib - python

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

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.

how to determine the figure size of an open figure using the gui tool?

Lets say I am plotting a pandas.DataFrame
df.plot(figsize = (10,10))
I usually start with the default figure size and adjust the figure size using the gui tool to achieve the format I want (making sure all legends look ok etc). However for the next plot, I don't want to repeat the same process. I would like to get the proper size and next time just call the plot with the hard-coded figure size that I got from tinkering with gui tool. Is there a way to get the current figure size from the gui?
Keep a reference to the plot axes:
ax = df.plot(figsize = (10,10))
You can then get the figure size later on using:
ax.get_figure().get_size_inches()

Save images of a matplotlib figure at different coordinates?

I want to create a big figure using matplotlib, and then save a few parts of it at different specific coordinates (so manual zooming after plt.show() is not an option - there is no guarantee I can zoom to some precise coordinates - or is there?). The picture is fairly large, so I don't want to generate it all over again and again, specifying xlim and ylim every time before plotting. Is there any way to change axes limits after the figure is created? And I am not using an ipython console, but I need to use it in a script.
There is no problem with using xlim and ylim here. Take the following example:
import matplotlib.pyplot as plt
plt.plot(range(20))
plt.savefig("1.png")
plt.xlim(0,10)
plt.savefig("2.png")
plt.xlim(0,30)
plt.savefig("3.png")
Here a diagonal line is plotted, then we zoom into the first half of the line, then we zoom back out. At each stage a new png file is created. There is no need for redrawing here.

On adjusting margins in matplotlib

I am trying to minimize margins around a 1X2 figure, a figure which are two stacked subplots. I searched a lot and came up with commands like:
self.figure.subplots_adjust(left=0.01, bottom=0.01, top=0.99, right=0.99)
Which leaves a large gap on top and between the subplots. Playing with these parameters, much less understanding them was tough (things like ValueError: bottom cannot be >= top)
My questions :
What is the command to completely minimize the margins?
What do these numbers mean, and what coordinate system does this follow (the non-standard percent thing and origin point of this coordinate system)? What are the special rules on top of this coordinate system?
Where is the exact point this command needs to be called? From experiment, I figured out it works after you create subplots. What if you need to call it repeatedly after you resize a window and need to resize the figure to fit inside?
What are the other methods of adjusting layouts, especially for a single subplot?
They're in figure coordinates: http://matplotlib.sourceforge.net/users/transforms_tutorial.html
To remove gaps between subplots, use the wspace and hspace keywords to subplots_adjust.
If you want to have things adjusted automatically, have a look at tight_layout
Gridspec: http://matplotlib.sourceforge.net/users/gridspec.html

How do I animate the ticks on the x-axis?

I have a matplotlib axes instance inside which I'm animating an AxesImage via blitting.
What I'd like to do is animate the ticks on the x-axis as well.
I am updating the data on the AxesImage (and subsequently) drawing its artist quite frequently, and on each update I'd like to move one extra tick placed to highlight the position of something.
This is what I'm doing right now:
axis = axes.get_xaxis
im.set_data(new_data)
axis.set_ticks([10,20,30,x,t])
axis.set_ticklabels(["p", "u", "z", "z", "i"])
axes.draw_artist(im)
axes.draw_artist(axis)
While I see the ticks correctly updating, the labels are not. I think that the axes bbox does not include the axes, is this possible? If so, how can I animate it? Should I copy and restore from somewhere else?
The axes bbox doesn't include anything outside of the "inside" of the axes (e.g. it doesn't include the tick labels, title, etc.)
One quick way around this is to just grab the entire region of the figure when you're blitting. (E.g. background = canvas.copy_from_bbox(fig.bbox))
This can cause problems if you have multiple subplots and only want to animate one of them. In that case, you can do something along the lines of background = canvas.copy_from_bbox(ax.bbox.expanded(1.1, 1.2)). You'll have to guesstimate the ratios you need, though.
If you need the exact extent of the tick labels, it's a bit trickier. The easiest way is to iterate through the ticklabel objects and get the union with ax.bbox. You can make this a one-liner: ax.bbox.union([label.get_window_extent() for label in ax.get_xticklabels()]).
At any rate, one of those three options should do what you need, I think.

Categories