Output figure size in Jupyter Notebook - matplotlib

I just upgraded my Jupyter version to 4.2.1 and it seems as though inline figures have gotten a lot larger for the same figsize.
Am I imagining this?
Can I change that without changing the figsize?

You can use top-level matplotlib settings like this:
import matplotlib as mpl
mpl.rcParams['figure.figsize'] = (10,10)
This will change default figure size to 10x10. More on that in the documentation: http://matplotlib.org/users/customizing.html

The scaling of the figure for figures with %matplotlib inline depends on the figure.dpi parameter. So if your figures are to small and you do not want to increase the figsize then you can just set
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 150 # default for me was 75
I also had the impression that the scaling changed at some point, but I guess this can also appear if you change your screen/resolution.

Related

Use a different matplotlibrc for savefig

I am using Jupyter Notebook, with a matplotlibrc style that's consistent with its theme set using jupyterthemes. That plotting style however does not look good if I want to export it to PNG to use it within my other documents.
How do I specify a different matplotlibrc when I do a savefig?
Most matplotlib style settings are applied at the moment the object they apply to is created.
You would hence need to create two different plots, one with the usual style of your notebook and another one with the style from the style file. The latter one would be the one to save.
A decent solution would be to create a plot in a function. You can then call this function within a context, with plt.style.context(<your style>): to give the figure a different style.
import matplotlib.pyplot as plt
def plot():
fig, ax = plt.subplots()
ax.plot([2,3,4], label="label")
ax.legend()
# Plot with general style of the notebook
plot()
# Plot with your chosen style for saved figures
with plt.style.context('ggplot'):
plot()
plt.savefig("dark.png")
#plt.close(plt.gcf()) # if you don't want to show this figure on screen
plt.show()
Relevant here: The matplotlib customizing guide.
Perusing matplotlib/__init__.py reveals a number of functions used for managing rcParams. To update rcParams from a file, use matplotlib.rc_file:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc_file('/tmp/matplotlibrc')
plt.plot([0,1], [0,10])
plt.savefig('/tmp/out.png')
with /tmp/matplotlibrc containing
lines.linewidth : 10 # line width in points
lines.linestyle : -- # dashed line
yields
PS. In hindsight, having found rc_file, googling shows it is documented here.

Matplotlib : Set default value for plt.axis to "equal"

I have many plots to draw and I wish to see all of them with the option plt.axis("equal").
Is there a way to fix Matplotlib default settings to plt.axis("equal") (as what is proposed by matplotlib.rcParams for most of the Matplolib paramaters) ?
Thanks,
Patrick
I have created an issue / feature request (8088) for this.
As it was pointed out there this rcParams doesn't work for pyplot.plot() yet. Hopefully it will be implemented soon.
However, the following works already and is the solution in case of images:
import matplotlib.pyplot as plt
plt.rcParams['image.aspect'] = 'equal'
a=[[1],[2]]
plt.imshow(a)

Matplotlib namespace issues?

I have a question regarding the Matplotlib.pyplot and namespaces.
See the following code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import cm
x=np.linspace(0,1,28)
color=iter(cm.gist_rainbow_r(np.linspace(0,1,28)))
plt.clf()
for s in range(28):
c=next(color)
plt.plot(x,x*s, c=c)
plt.show()
The idea was to have the plots in different colors of the rainbow map.
Now what happens is that on first execution it works, but then things are getting weird.
On several consecutive executions the map is stopped being used and instead of that the default map is used.
I see that the problem may lie within the "c=c" in the plot function, but I have played around with different namings "c", "color", .... and could not find the systematic of the issue here.
Can someone reproduce the problem and (try the code at least 5 times or so consecutively) is able to explain, what is going on here?
Thanks
This is known issue with mpl + python3.4+ that has been fixed in mpl v1.5+.
Many of the style parameters have multiple aliases (ex 'c' vs 'color') which mpl was not merging properly and the artists were essentially getting told two different colors which internally means there is a dictionary with both 'c' and 'color' in it.
In python 3.4+ process-to-process order of iteration of dictionaries is random by default due to the seed for the underlying hash table being randomized (this was to prevent a possible DOS attack based on intentional hash table collisions). In older versions of python it so happened that the user supplied color always came later in the iteration order so things coincidentally worked.
The simple work around (iirc) is to use plot(x, y, color=c) or update to mpl 1.5.1.

matplotlib get rid of max_open_warning output

I wrote a script that calls functions from QIIME to build a bunch of plots among other things. Everything runs fine to completion, but matplotlib always throws the following feedback for every plot it creates (super annoying):
/usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.py:412: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (matplotlib.pyplot.figure) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam figure.max_num_figures).
max_open_warning, RuntimeWarning)
I found this page which seems to explain how to fix this problem , but after I follow directions, nothing changes:
import matplotlib as mpl
mpl.rcParams[figure.max_open_warning'] = 0
I went into the file after calling matplotlib directly from python to see which rcparams file I should be investigating and manually changed the 20 to 0. Still no change. In case the documentation was incorrect, I also changed it to 1000, and still am getting the same warning messages.
I understand that this could be a problem for people running on computers with limited power, but that isn't a problem in my case. How can I make this feedback go away permanently?
Try setting it this way:
import matplotlib as plt
plt.rcParams.update({'figure.max_open_warning': 0})
Not sure exactly why this works, but it mirrors the way I have changed the font size in the past and seems to fix the warnings for me.
Another way I just tried and it worked:
import matplotlib as mpl
mpl.rc('figure', max_open_warning = 0)
When using Seaborn you can do it like this
import seaborn as sns
sns.set_theme(rc={'figure.max_open_warning': 0})
Check out this article which basically says to plt.close(fig1) after you're done with fig1. This way you don't have too many figs floating around in memory.
In Matplotlib, figure.max_open_warning is a configuration parameter that determines the maximum number of figures that can be opened before a warning is issued. By default, the value of this parameter is 20. This means that if you open more than 20 figures in a single Matplotlib session, you will see a warning message. You can change the value of this parameter by using the matplotlib.rcParams function. For example:
import matplotlib.pyplot as plt
plt.rcParams['figure.max_open_warning'] = 50
This will set the value of figure.max_open_warning to 50, so that you will see a warning message if you open more than 50 figures in a single Matplotlib session.

inline images have low quality

I'm loading a TIF file with scikit-image and displaying it inline in an ipython notebook (version 2.2.0). This works, however, the image is quite small when first displayed, and when I resize it using the draggable handle on the bottom right of the image, it just rescales the image while retaining the resolution of the original, so it's very blurry when enlarged. It's basically as if ipython is converting my image into a thumbnail on the fly.
I've tried using matplotlib's plt.imshow() as well, which has the exact same result. I'm starting the notebook with ipython notebook --pylab inline.
from skimage import io
import matplotlib.pyplot as plt
image_stack = io.MultiImage("my_image.tif")
image = image_stack[0] # it's a multi-page TIF, this gets the first image in the stack
io.imshow(image) # or plt.imshow(image)
io.show() # or plt.show()
To change the "%matplotlib inline" figure resolution on the notebook do:
import matplotlib as mpl
mpl.rcParams['figure.dpi']= dpi
I recommend setting the dpi somewhere between 150 and 300 if you are going to download/print the notebook. Ensure that %matplotlib inline runs before the mpl.rcParams['figure.dpi']= dpi otherwise the magic command resets the dpi to its default value (credits to #fabioedoardoluigialberto for noticing this).
The snipppet below only changes the dpi of figures saved through the savefig method, not of inline generated figures.
import matplotlib as mpl
mpl.rc("savefig", dpi=dpi)
According to https://www.reddit.com/r/IPython/comments/1kg9e2/ipython_tip_for_getting_better_quality_inline/
You could also execute this magic in your cell:
%config InlineBackend.figure_format = 'svg'
The print quality will look significantly better. You can also change svg to retina, to use higher-res PNGs (not as nice). Nevertheless, note that if your picture becomes too complicated, the svg picture will have a much larger size than that of the retina picture
The resolution of inline matplotlib figures is downscaled a bit from what you would see in a GUI window or saved image, presumably to save space in the notebook file. To change it, you can do:
import matplotlib as mpl
mpl.rc("figure", dpi=dpi)
Where dpi is some number that will control the size/resolution of the inline plots. I believe the inline default is 80, and the default elsewhere with matplotlib is 100.
The reason scaling the resulting plot by dragging the handle doesn't work is that the plot is rendered as a png, so scaling it zooms but does not change the intrinsic resolution.
Assuming this is the same thing that happens with iPython notebook (with %matplotlib inline) when you go to drag and resize the image, the fix is fairly simple.
If you just create a figure with a different default size, then the resolution also increases with the size of the default (Change resolution of imshow in ipython). For example:
fig = plt.figure(figsize = (10,10))
ax = fig.add_subplot(111)
ax.imshow(array)
Something like this should increase the resolution of the thing you are trying to plot. This seemed to work for me with your code:
from skimage import io
import matplotlib.pyplot as plt
%matplotlib inline
image_stack = io.MultiImage("my_image.tif")
image = image_stack[0]
fig = plt.figure(figsize= (20,20)) #create an empty figure to plot into with 20x20 size
io.imshow(image)
io.show()