Matplotlib: poor resolution of PDF figures with hatching - python

When using Matplotlib to generate figures with hatching (e.g. pie, bar, bubble charts), I'm having some trouble getting decent resolution out of the PDF version of the figure. Saving as EPS is fine, but as soon as I use epstopdf or MPL's savefig(*.pdf), the hatching becomes pixellated and distored... the vector nature of the image appears to have been lost.
See minimal code below.
from matplotlib import pyplot as plt
# Define hatching styles
hatching = ["/", "o"]
fig, ax = plt.subplots()
wedges, texts = ax.pie([0.4, 0.6], colors=("SteelBlue", "Tomato"))
# Apply the hatching
for j, patch in enumerate(wedges): patch.set_hatch(hatching[j])
fig.savefig("hatchtest.pdf")
I've used Gimp to zoom in on a part of the plot to illustrate the difference...
Zoomed in on the EPS figure
Zoomed in on the PDF figure
As for system specific details, I'm using Ubuntu 13.04, Python 2.7.4 with MPL 1.2.1. I've tried different backends but nothing seems to resolve this. I'd ideally like to have nice vector images in EPS and PDF so that it's all journal-friendly. Any pointers would be much appreciated.

Just a problem with Evince PDF viewer. Viewing in Adobe Reader or printing the plot gives the desired result.

Related

Python - save a figure with the same size and setting

I plot figures a lot during my python (through Spyder env.) usage. However, when I try to use plt.savefig('figure.png'), the saved figure has a different size from the inline figure plotted on Spyder.
For ex., when I use this command:
plt.savefig('fig1.png')
The saved figure looks like this:
Note that there's something weird with the saved figure, e.g.: the title is cropped, the size is not proportional.
However, the following is the inline figure:
I tried to modify the size through matplotlib.pyplot documentation but couldn't find such setting. Does anyone know how to save the figure with the exact setting as the inline plot?
The inline figure size plotted in Spyder (or any other IDE or editor) depends on how the editor handles showing figures.
If you want to have an exact size as output of your code, use figsize before plotting code. (It uses inches)
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
# Code to produce figure
You can also determine DPI when creating figure or saving.
plt.figure(figsize=(10, 10), dpi=300)
# or
plt.savefig(file_path, dpi=300)

Issue with colorbar in pylab

I am trying to plot a two dimensional numpy matrix (say, Kappa) using pcolor .
The skeleton of the code is this:
from pylab import pcolor, show, colorbar, xticks, yticks
import numpy as np
plt.figure(1)
pcolor(np.transpose(Kappa))
plt.colorbar()
plt.tight_layout()
plt.show()
At the top of the colorbar, I see a weird way in which the highest scale of the colorbar is written. I have attached a picture of the the said output (and I have highlighted the troublesome part by putting it inside a red box.)
Following suggestions, I have uploaded the matrix to my Google Drive. You can use this link to access the matrix.
I am wondering if anyone has faced similar issues with colorbars in pylab? I will appreciate any help.

Vector graphics + matplotlib pcolorfast

To keep it short: Is there a way to export plots created with methods like
pcolorfast which basically draw pixels as "real" vector graphics?
I tried to do just that using savefig and saving to a PDF but what would happen is that the plot was actually a vector graphic but the parts drawn by pcolorfast(so basically, what is inside the axes) something like a bitmap. - I checked this using Inkscape.
This resulted in really low resolution plots even though the arrays drawn with pcolorfast where about 3000x4000. I achieved higher resolution by increasing the dpi when exporting, but I'd really appreciate a conversion to a real vector graphic.
Edit: I updated my original code by the piece of code below that should serve to illustrate what exactly I am doing. I tried to involucrate the rasterized tip, but it has had no effect. I still end up with a supersmall PDF-file where the plots are acually raster images (png). I am going to provide you with the data I used and the resulting PDF.
http://www.megafileupload.com/k5ku/test_array1.txt
http://www.megafileupload.com/k5kv/test_array2.txt
http://www.megafileupload.com/k5kw/test.pdf
import numpy as np
import matplotlib.pyplot as plt
arr1= np.loadtxt("test_array1.txt")
arr2= np.loadtxt("test_array2.txt")
fig, (ax1, ax2)=plt.subplots(1, 2)
ax1.set_rasterized(False)
ax1.pcolorfast(arr1)
ax2.pcolorfast(arr2, rasterized=False)
plt.show()
fig.set_rasterized(False)
fig.savefig("test.pdf")

Matplotlib saves pdf with data outside set

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.

Saving images in Python at a very high 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.)

Categories

Resources