I am trying to save a plot into a file using plt.savefig, however I am dissatisfied with the output picture quality. Changing dpi option doesn't help.
plt.savefig('filename.png', dpi=1200, format='png', bbox_inches='tight')
I tried saving to 'svg' and 'eps' - makes no difference. I wonder if the problem is with something else, like version of some library or OS or something alike. It also looks like the problem is not with resolution but the way lines and symbols are drawn - too bold.
plt.show() shows significantly better picture, and I can save it to png with satisfying quality - and surprisingly file size is about 8 times smaller (because of compressing, I suppose, which is fine.)
Part of the picture saved using savefig()
The same part of the picture saved from plot.show()
Figsize option did the trick for me.
The idea is that default parameters for saving to file and for displaying the chart are different for different devices. That's why representation was different in my case.
It's possible to adjust settings manually (as Piotrek suggests), but for me it was enough just to increase figure size - this setting is shared and allows python to auto-adjust visualization.
More details are on the page Piotrek mentioned, answered by doug and Karmel.
I have several subplots, so i used it like that:
fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(20, 10))
For one plot case command is like that:
plt.figure(figsize=(20,10))
P.S. figsize parameters are in inches, not pixels.
Have a look here: Styles and Futurile
In short, you can experiment with the following options to edit the line, ticks etc.
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = 'Ubuntu'
plt.rcParams['font.monospace'] = 'Ubuntu Mono'
plt.rcParams['font.size'] = 10
plt.rcParams['axes.labelsize'] = 10
plt.rcParams['axes.labelweight'] = 'bold'
plt.rcParams['axes.titlesize'] = 10
plt.rcParams['xtick.labelsize'] = 8
plt.rcParams['ytick.labelsize'] = 8
plt.rcParams['legend.fontsize'] = 10
plt.rcParams['figure.titlesize'] = 12
Also have a look at this topic:
matplotlib savefig() plots different from show()
Related
I have numpy array of shape (4000000, 200, 3), where first dimension relates to image height, second - width.
I m confused how to save this image as png (or any other format) with high resolution, because when I set dpi = 5000 then I get mermory error
Here is my code
fig, ax = plt.subplots()
im = ax.imshow(final_image_train)
ax.axis('off')
plt.savefig('final.png', dpi = 5000, bbox_inches = 'tight')
Any suggestions are appreciated.
Are you using the default figsize? This parameter gives a determined amount of space to the elements inside the figure, including ticklabels.
Then, if you know which pixel size is needed, for example (1200, 600), you need to choose the combination of figure size and dpi. An example relation would be:
figsize=(12,6) , dpi=100
figsize=( 8,4) , dpi=150
figsize=( 6,3) , dpi=200
There is more about it on other stack overflow posts like this one. Your dpi seems to be extremely high, maybe you need to calculate the dpi and figsize better...
Now, this answer part is just a recommendation. Is the matplotlib and .png mandatory? If not, have a look at the plotly library, which lets you create interactive plots, which are really good if you need to explore a lot of data (.html format). You have the offline version of the library, if you are interested. Also, here you have subplots examples.
I use matplotlib to generate data analysis plots, which I then show to people at conferences, in publications etc. I normally store all the data and scripts that generate every interesting/useful plot, just in case I need to update the charts at some point after creating them. Here's an example of my box-standard piece of code that generates the below plot:
# In[Imports]:
import pandas, matplotlib, matplotlib.pyplot
# In[Plot formatting]:
ticksFontSize = 18
labelsFontSize = 30
legendFontSize = 16
cm=matplotlib.pyplot.cm.get_cmap('viridis')
matplotlib.rc('xtick', labelsize=ticksFontSize)
matplotlib.rc('ytick', labelsize=ticksFontSize)
# In[Read the data]:
# CDF of TLE update frequenies
dfGood=pandas.read_csv('blue.csv',sep=',',header=None)
epochsGood=dfGood[0].values
cdfsGood=dfGood[1].values
# In[Plot the data]:
fig,ax=matplotlib.pyplot.subplots(1,1,sharex=True,figsize=(14,8))
ax.scatter(epochsGood,cdfsGood,c='indigo',marker='o',lw=0,s=30)
ax.set_xlabel(r"$TLE\ update\ frequency\ (orbital\ periods)$",
size=labelsFontSize)
ax.set_ylabel(r"$Cumulative\ Distribution\ Function\ (-)$",
fontsize=labelsFontSize)
ax.grid(linewidth=1)
ax.tick_params(axis='both',reset=False,which='both',
length=5,width=1.5)
ax.tick_params(axis='x', which='major', pad=15)
ax.set_xlim(0,5)
ax.set_ylim(0,1.1)
matplotlib.pyplot.subplots_adjust(left=0.1,right=0.95,
bottom=0.15,top=0.9)
fig.show()
Recently (within the last few months, but it could have been a long overdue update...), I updated matplotlib and the above script started generating a differently formatted plot:
The clipped Y-axis is no biggie, I can just live with that and adjust the plot/axis. What I am a bit perplexed about is the changed font. It appears that sometime during the matplotlib update the matplotlibrc file has changed. I can live with that and explicitly set matplotlibrc properties in my scripts, or set label text properties on a per-label basis as shown in this answer. But I have no idea how to go back to the previous formatting, i.e. what text properties to set. Any ideas?
Some useful info
Current Python version = 3.5.4
Python version I used to generate the "old plot" = 3.5.something
Current matplotlib version = 2.2.2
matplotlib version I used to generate the "old plot" = I wish I knew...
The default math font has changed in version 2.x from "Computer Modern" to "DejaVu Sans". You can change it in your script as mentioned in the documentation back to the previous version:
from matplotlib import pyplot as plt
plt.rcParams['mathtext.fontset'] = 'cm'
plt.rcParams['mathtext.rm'] = 'serif'
Sample output (without your data because your question does not contain an MCVE):
I'm having an issue when trying to save a bar plot as an svg. Specifically, when I save the bar plot as a PDF with savefig, I get the correct result. However, when I save it as an SVG, the bars do not terminate at the x-axis as they should but descend past the bottom of the figure. This problem only occurs when I use the log scale for the bar plot. Otherwise, everything is hunky dory.
Here is the code saving the plot as both an SVG and a PDF:
import matplotlib.pyplot as plt
import numpy as np
N = 10
ind = np.arange(N)
series1 = xrange(N)
series2 = [ N - s1_i for s1_i in series1 ]
fig, ax = plt.subplots()
width = 0.2
rects = [ ax.bar(ind, series1, width, color='r', log=True),
ax.bar(ind + width, series2, width, color='b', log=True) ]
plt.savefig("test.pdf")
plt.savefig("test.svg")
Here are the two sample images:
You can see there are no glaring issues with the PDF version.
The SVG version has bars that are not properly clipped, which is wrong.
Update: In response to tcaswell
I'm using Ubuntu 14.04 (kernel version is 3.16.0) with Python 2.7.6, Matplotlib version 1.3.1, numpy version 1.8.2.
I've tried viewing the SVG both with display and rsvg-view-3, and both show the same result; if I convert it to a PDF using ImageMagick's convert command line tool and open it with evince or another viewer such as acroread, the image remains flawed (not particularly surprising).
This is a known bug in librsvg (and limitation in libQtSvg which only handles a very restricted sub-set of SVG (1.2 tiny) which does not include clipping at all).
The svg will render correctly in any modern browser.
There is a much longer discussion at https://github.com/matplotlib/matplotlib/issues/4341, but the long and short of it is that the renderer is buggy.
I am using word cloud with some txt files. How do I change this example if I wanted to 1) increase resolution and 2) remove empty border.
#!/usr/bin/env python2
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""
from os import path
import matplotlib.pyplot as plt
from wordcloud import WordCloud
d = path.dirname(__file__)
# Read the whole text.
text = open(path.join(d, 'constitution.txt')).read()
wordcloud = WordCloud().generate(text)
# Open a plot of the generated image.
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
You can't increase the resolution of the image in plt.show() since that is determined by your screen, but you can increase the size. This allows it to scale, zoom, etc. without blurring. To do this pass dimensions to WordCloud, e.g.
wordcloud = WordCloud(width=800, height=400).generate(text)
However, this just determines the size of the image created by WordCloud. When you display this using matplotlib it is scaled to the size of the plot canvas, which is (by default) around 800x600 and you again lose quality. To fix this you need to specify the size of the figure before you call imshow, e.g.
plt.figure( figsize=(20,10) )
plt.imshow(wordcloud)
By doing this I can successfully create a 2000x1000 high resolution word cloud.
For your second question (removing the border) first we could set the border to black, so it is less apparent, e.g.
plt.figure( figsize=(20,10), facecolor='k' )
You can also shrink the size of the border by using tight_layout, e.g.
plt.tight_layout(pad=0)
The final code:
# Read the whole text.
text = open(path.join(d, 'constitution.txt')).read()
wordcloud = WordCloud(width=1600, height=800).generate(text)
# Open a plot of the generated image.
plt.figure( figsize=(20,10), facecolor='k')
plt.imshow(wordcloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()
By replacing the last two lines with the following you can get the final output shown below:
plt.savefig('wordcloud.png', facecolor='k', bbox_inches='tight')
If you are trying to use an image as a mask, make sure to use a big image to get better image quality.. I spent hours figuring this out.
Heres an example of a code snippet I used
mask = np.array(Image.open('path_to_your_image'))
image_colors = ImageColorGenerator(mask)
wordcloud = WordCloud(width=1600, height=800, background_color="rgba(255, 255, 255, 0)", mask=mask
,color_func = image_colors).generate_from_frequencies(x)
# Display the generated image:
plt.figure( figsize=(20,10) )
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
It is very simple, plt.tight_layout(pad=0) does the job, reduces the space in the background, removing the excess padding.
You can use the method to_svg and get a resolution however high you want.
with open("Output.svg", "w") as text_file:
text_file.write(wc.to_svg())
Try an example by appending these two lines to this file, and the result is gorgeous.
(Other answers have addressed the border problem, and also the example doe not have a border.)
In case you run into the issue of slower application while improving the resolution ie. in a web application, the WordCloud documentation advises that you utilize the scale parameter along with the canvas' width & height params to get a resolution & response time that works for your use case.
Blurry wordclouds - I've been wrestling with this. For my use, I found that too large a differential in the between the most frequent word occurrences and those with few occurrences left the lower-count words unreadable. When I scaled the more frequent counts to reduce the differential, all the lower-frequency words were much more readable.
This question already has answers here:
How do I change the size of figures drawn with Matplotlib?
(14 answers)
Closed 1 year ago.
I want to obtain fig1 exactly of 4 by 3 inch sized, and in tiff format correcting the program below:
import matplotlib.pyplot as plt
list1 = [3,4,5,6,9,12]
list2 = [8,12,14,15,17,20]
plt.plot(list1, list2)
plt.savefig('fig1.png', dpi = 300)
plt.close()
You can set the figure size if you explicitly create the figure with
plt.figure(figsize=(3,4))
You need to set figure size before calling plt.plot()
To change the format of the saved figure just change the extension in the file name. However, I don't know if any of matplotlib backends support tiff
You can change the size of the plot by adding this before you create the figure.
plt.rcParams["figure.figsize"] = [16,9]
The first part (setting the output size explictly) isn't too hard:
import matplotlib.pyplot as plt
list1 = [3,4,5,6,9,12]
list2 = [8,12,14,15,17,20]
fig = plt.figure(figsize=(4,3))
ax = fig.add_subplot(111)
ax.plot(list1, list2)
fig.savefig('fig1.png', dpi = 300)
fig.close()
But after a quick google search on matplotlib + tiff, I'm not convinced that matplotlib can make tiff plots. There is some mention of the GDK backend being able to do it.
One option would be to convert the output with a tool like imagemagick's convert.
(Another option is to wait around here until a real matplotlib expert shows up and proves me wrong ;-)
If you need to change the figure size after you have created it, use the methods
fig = plt.figure()
fig.set_figheight(value_height)
fig.set_figwidth(value_width)
where value_height and value_width are in inches. For me this is the most practical way.