I have been using Cartopy to plot data using 'equal' aspect, resulting in all manner of non-square Axes sizes. These usually look OK in Jupyter notebooks, but when saving the images (or when doing more complicated operations like adding colorbars), the resulting Figures are often huge, with a lot of blank space around the Axes plotting area. They also look bad when using %matplotlib widget. An example is provided below.
It seems that the figure in this case is too big in at least one dimension. I would like to remove that extra space in the final output figure, without shrinking the size of the plotting area itself.
I know that I can adjust the figure size itself with .set_figwidth and .set_figheight, as well as setting figsize= upon creation. But I don't know how to figure out the correct dimensions to shrink the figure without shrinking the axes, and I haven't seen any way to do this automatically. What's the correct solution? I would like to avoid manually editing my images after creating them!
When I use Matplotlib's plt.show() I get a nice Plot which can can be zoomed to very high precision(practically infinite). But when I save it as a image it loses all this information gives information depending on resolution.
Is there any way I can save the plot with the entire information? i.e Like those interactive plots which can rescaled at any time?
P.S- I know I can set dpi to get high quality images. This is not what I want. I want image similar to Plot which python shows when I run the program. What format is that? Or is it just very high resolution image?
Note- I am plotting .csv files which includes data varying from 10^(-10) to 100's. Thus when I save the plot as .png file I lose all the information/kinks of graph at verŠ½ small scales and only retain features from 1-100.
Maybe the interactive graphic library bokeh is an option for you. See here. It's API is just little different from what you know from matplotlib.
Bokeh creates plots as html files that you can view in your browser. For each graphic you can select wheel zoom to zoom interactively into your graphic. You can change interactively the range that you want to be plotted. Therefore you don't loose information in your graphic.
I have a problem with Matplotlib. I usually make big plots with many data points and then, after zooming or setting limits, I save in pdf only a specific subset of the original plot. The problem comes when I open this file: matplotlib saves all the data into the pdf making not visible the one outside of the range. This makes almost impossible to open afterwards those plots or to import them into latex.
Any idea of how I could solve this problem is really welcome.
Thanks a lot
If you don't have a requirement to use PDF figures, you can save the matplotlib figures as .png; this format just contains the data on the screen, e.g. I tried saving a large scatter plot as PDF, its size was 198M; as png it came out as 270K; plus I've never had any problems using png inside latex.
I have not tested that this will work, but it might be worth rasterizing some of the artists:
fig, ax = plt.subplots()
ax.imshow(..., rasterized=True)
fig.savefig('test.png', dpi=600)
which will rasterize the artist when saving to vector formats. If you use a high enough dpi this should give you reasonable quality.
How can I save Python plots at very high quality?
That is, when I keep zooming in on the object saved in a PDF file, why isn't there any blurring?
Also, what would be the best mode to save it in?
png, eps? Or some other? I can't do pdf, because there is a hidden number that happens that mess with Latexmk compilation.
If you are using Matplotlib and are trying to get good figures in a LaTeX document, save as an EPS. Specifically, try something like this after running the commands to plot the image:
plt.savefig('destination_path.eps', format='eps')
I have found that EPS files work best and the dpi parameter is what really makes them look good in a document.
To specify the orientation of the figure before saving, simply call the following before the plt.savefig call, but after creating the plot (assuming you have plotted using an axes with the name ax):
ax.view_init(elev=elevation_angle, azim=azimuthal_angle)
Where elevation_angle is a number (in degrees) specifying the polar angle (down from vertical z axis) and the azimuthal_angle specifies the azimuthal angle (around the z axis).
I find that it is easiest to determine these values by first plotting the image and then rotating it and watching the current values of the angles appear towards the bottom of the window just below the actual plot. Keep in mind that the x, y, z, positions appear by default, but they are replaced with the two angles when you start to click+drag+rotate the image.
Just to add my results, also using Matplotlib.
.eps made all my text bold and removed transparency. .svg gave me high-resolution pictures that actually looked like my graph.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# Do the plot code
fig.savefig('myimage.svg', format='svg', dpi=1200)
I used 1200 dpi because a lot of scientific journals require images in 1200 / 600 / 300 dpi, depending on what the image is of. Convert to desired dpi and format in GIMP or Inkscape.
Obviously the dpi doesn't matter since .svg are vector graphics and have "infinite resolution".
You can save to a figure that is 1920x1080 (or 1080p) using:
fig = plt.figure(figsize=(19.20,10.80))
You can also go much higher or lower. The above solutions work well for printing, but these days you want the created image to go into a PNG/JPG or appear in a wide screen format.
Okay, I found spencerlyon2's answer working. However, in case anybody would find himself/herself not knowing what to do with that one line, I had to do it this way:
beingsaved = plt.figure()
# Some scatter plots
plt.scatter(X_1_x, X_1_y)
plt.scatter(X_2_x, X_2_y)
beingsaved.savefig('destination_path.eps', format='eps', dpi=1000)
In case you are working with seaborn plots, instead of Matplotlib, you can save a .png image like this:
Let's suppose you have a matrix object (either Pandas or NumPy), and you want to take a heatmap:
import seaborn as sb
image = sb.heatmap(matrix) # This gets you the heatmap
image.figure.savefig("C:/Your/Path/ ... /your_image.png") # This saves it
This code is compatible with the latest version of Seaborn. Other code around Stack Overflow worked only for previous versions.
Another way I like is this. I set the size of the next image as follows:
plt.subplots(figsize=(15,15))
And then later I plot the output in the console, from which I can copy-paste it where I want. (Since Seaborn is built on top of Matplotlib, there will not be any problem.)
I'm working on an assignment which involves the need to show multiple figures on screen as the script is run (and also to save them). I am having to use both imshow and show to get the images up on the screen. This works fine, but I have read that show() should only be used once per script. Is there another way to display the image? The saved image files are also saving as blank 800x600 white images. Here's my code:
img = np.zeros((100,100))
plt.figure(0)
plt.imshow(img)
plt.show()
plt.savefig("images/img.png")
plt.close(0)
Each other figure is following the same syntax (obviously with different image names and a new figure number.
Thanks!
Generally, your approach using figure() to create a new figure object for each figure you want to display on the screen and save to a file is fine, if this is what you want to hear.
I'm not sure what your actual question is in this respect, so I would seriously recommend editing your question if there is something else you want to know.
Regarding the second issue: depending on the backend in use, show() may destroy objects in the figure (upon closing), which is why you generally should first savefig() and then show(). This is documented here.