matplotlibrc rcParams modified for Jupyter inline plots - python

I have seen this question come up a couple of times, but I think this information changes as jupyter/ipython get updated. I am currently running python 3.5, jupyter (latest) and matplotlib 2.0.
The %matplotlib inline plots have custom properties that are set after the matplotlibrc file is imported. The most annoying of these is that the figure.facecolor property is set to be transparent which wreaks havoc when copy/pasting plots so I have to reset this property in the notebook. I cannot seem to find where this property is changed, or if it is possible to create a configuration profile somewhere to change these special inline plot settings
My question is, is it possible to change these settings, and if so, how would I do that?

Some of the rcParameters are set specifically for the inline backend. Those are
{'figure.figsize': (6.0,4.0),
'figure.facecolor': (1,1,1,0), # play nicely with white background in the Qt and notebook
'figure.edgecolor': (1,1,1,0),
'font.size': 10, # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
'figure.dpi': 72, # 72 dpi matches SVG/qtconsole
'figure.subplot.bottom' : .125 # 10pt still needs a little more room on the xlabel
}
And the place where they reside is the ipykernel/pylab/config.py file.
This file can be edited to obtain the desired behaviour, e.g. by changing the facecolor to 'figure.facecolor': (1,1,1,1) (no transparency).
Another option is the following:
The rcParameters are defined as part of the InlineBackend class, specifically the InlineBackend.rc attribute which is a traitlets.Dict object.
Those can be changed using the ipython configuration system as follows.
From the command line type ipython profile create which will generate the default configuration files in ~/.ipython. In the main configuration file ~/.ipython/ipython_config.py include the line:
c.InlineBackend.rc.update({"figure.facecolor": "white"})

The accepted answer was correct at the time. Recent update: The inline-specific backend will no longer override Matplotlib's defaults, see this commit from 12th of May 2022.
Before this recent change, the dict with the override values had moved to
matplotlib-inline/matplotlib_inline/config.py

Related

Some dict properties in seaborn set_style function don't work

X = np.arange(20)
y = np.log(X**2)
# set title in Chinese
plt.title('你好')
sns.set_style({'axes.facecolor':'red','font.sans-serif':['SimSun']})
sns.lineplot(X,y,color="blue")
When I run this code first time in Jupyter,the title can be shown correctly, that means the font.sans-serif property worked well, but the backgroundcolor is not red.
But when I run the same code again for the second time, the axes.facecolor property works,the backgroundcolor changes to be red.
That makes me confused, why did this happend? And is there any other property like this?
According to the seaborn style aesthetics configuration tutorial, local style control should be done with (for instance):
with sns.axes_style("darkgrid"):
sns.lineplot(X,y,color="blue")
For global settings, use sns.set_style(...) before any plotting statement in order to it to be taken into account. This is why you have to launch it twice in Jupyter to take effect. Dedicating a cell to it right after the import could be a better solution.

Remove toolbar buttons in matplotlib

I'm trying to remove all toolbar buttons except 'save' button.
I managed to remove the buttons but I couldn't find a way to remove the 'Configure subplots' button.
Here is a simple code just to illustrate how i tried to remove the buttons:
import matplotlib.pyplot as plt
plt.rcParams['toolbar'] = 'toolmanager'
# I managed to find the buttons' names while reading the backend_bases.py
# I didn't find the subplot configuration button name so i didn't include it here
buttons_names = ['forward', 'back', 'pan', 'zoom', 'home', 'help']
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1, 2], [1, 2])
# removing buttons using
for button in buttons_names:
fig.canvas.manager.toolmanager.remove_tool(button)
plt.show()
I looked at backend_bases.py and commented the subplots tuple which now looks like this: (I don't know if there is a reference to 'subplots configuration' button somewhere else in order to remove the button)
toolitems = (
('Home', 'Reset original view', 'home', 'home'),
('Back', 'Back to previous view', 'back', 'back'),
('Forward', 'Forward to next view', 'forward', 'forward'),
(None, None, None, None),
('Pan', 'Pan axes with left mouse, zoom with right', 'move', 'pan'),
('Zoom', 'Zoom to rectangle', 'zoom_to_rect', 'zoom'),
#('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'),
(None, None, None, None),
('Save', 'Save the figure', 'filesave', 'save_figure'),
)
Also when i run the code above, it also shows a warning:
UserWarning: Treat the new Tool classes introduced in v1.5 as experimental for now, the API will likely change in version 2.1, and some tools might change name
'experimental for now, the API will likely change in ' +
I looked at other solutions but none worked for me, and some of them use gui frameworks which is not what i'm looking for.
Is there any other way that can remove the button, or is there a name for subplots configuration button that i can include in the buttons_names list in the code above?
Update: Ok, it seems that the problem was associated with python version. I was using python 3.7.0. I updated to 3.7.4, added 'subplots' to buttons_names list and it worked. But there are 2 issues:
When the chart is shown, it displays a warning:
Treat the new Tool classes introduced in v1.5 as experimental for now, the API will likely change in version 2.1 and perhaps the rcParam as well
C:/Users/usr/Documents/MyPrograms/Python/Daily Expense/Chart.py:36: UserWarning: The new Tool classes introduced in v1.5 are experimental; their API (including names) will likely change in future versions.
fig = plt.figure()
The toolbar is now shown on top, it used to be under the chart and i want to make it display under the chart as it used to.
Currently i'm using Python 3.7.4, matplotlib version 3.1.1, Windows 10
How can i fix these 2 things?
Apparently the name is "subplots":
fig.canvas.manager.toolmanager.remove_tool("subplots")
Re part 1 of your question, I've been able to suppress that annoying warning by doing this:
import sys
import matplotlib.pyplot as plt
if not sys.warnoptions:
import warnings
warnings.filterwarnings("ignore", category=UserWarning,
message="Treat the new Tool classes introduced in v1.5 as experimental for now")
plt.rcParams['toolbar'] = 'toolmanager'
You may have to edit the value of the message arg if the warning message changes with later matplotlib versions though. See the Python docs for the Warnings Filter.

Change default matplotlib value in jupyter notebook

I was wondering how you can change the matplotlib.rcParams permanently instead of indicating it every time when you open jupyter notebook. (like change in the profile as the default value).
Thanks
A short answer, also for personal reference...
I would still prefer indicating it in the code though. However it doesn't have to be done for every single parameters as it can be done in one line calling for a style file for instance.
Anyway, here are several ways of doing so, from the most permanent change to the most soft and subtle way of changing the parameters:
1. Change default config file
Change the default parameters in matplotlibrc file, you can find its location with:
import matplotlib as mpl
mpl.get_configdir()
2. Modify iPython profile
Change how matplotlib default options are loaded in iPython by modifying options in ~/.ipython/profile_default/ipython_kernel_config.py, or wherever your configuraiton file is (ipython locate profile to find out) (see this answer for details)
3. Create your own styles
You can create your own custom rcParams files and store them in .config/matplotlib/stylelib/*.mplstyle or wherever os.path.join(matplotlib.get_configdir(), stylelib) is.
The file should be in the following format, similar to matplotlibrc, e.g. my_dark.mplstyle:
axes.labelcolor: white
axes.facecolor : 333333
axes.edgecolor : white
ytick.color : white
xtick.color : white
text.color : white
figure.facecolor : 0D0D0D
This is an example of a style for a dark background with white axes, and white tick labels...
To use it, before your plots, call:
import matplotlib.pyplot as plt
plt.style.use("my_dark")
# Note that matplotlib has already several default styles you can chose from
You can overlay styles by using several ones at once, the last one overwrites its predecessors' parameters. This can be useful to keep e.g. font variables from a certain style (paper-like, presentation) but simultaneously toggle a dark mode on top, by overwriting all color-related parameters.
With something like plt.style.use(["paper_fonts", "my_dark"])
More info in their documentation.
4. Context manager for rc_params
You can also use a context manager, this option is great in my opinion, to do something like:
import matplotlib as mpl
import matplotlib.pyplot as plt
with mpl.rc_context(rc={'text.usetex': True}, fname='screen.rc'):
plt.plot(x, a)
plt.plot(x, b)
Here we used a first set of parameters as defined in the file screen.rc then tweak the text.usetex value solely for the plt.plot(x,a) while plt.plot(x, b) will be using another (default here) set of rc parameters.
Again, see the doc for more information.

Jupyter notebook inline plotting breaks, when loading matplotlib rcparams from matplotlibrc file

I want to write a module with a function to set default style parameters from a matplotlibrc file. A minimal example of the module style.py:
import matplotlib as mpl
def set_default():
mpl.rc_file('./matplotlibrc')
If I want to use the module in a jupyter notebook with inline plotting, the inline plot is not shown, when I call style.set_default() before having plotted anything before.
So If I call
%matplotlib inline
style.set_default()
plt.plot()
the output is an empty list and no plot is shown. If I call e.g.
plt.plot()
after enabling inline plotting and before calling the set_default function, the output of both plot calls is shown inline.
This even happens, when the matplotlibrc file is empty as it is in my minimal example.
Does anyone understand why this happens and has an idea how to solve this problem or another way how to set a default style in a module using a matplotlibrc file?
Here are also two images of both cases in a jupyter notebook:
inline broken
inline working
Extra question: Why is the second plot in the second case larger, when the loaded matplotlibrc is empty?
Short version: Use mpl.style.use instead of mpl.rc_file.
Long version:
You may print out the backend in use to see what is going on.
import matplotlib as mpl
def set_default():
mpl.rc_file('matplotlibrc.txt') # this is an empty file
import matplotlib.pyplot as plt
print mpl.get_backend()
# This prints u'TkAgg' (in my case) the default backend in use
# due to my rc Params
%matplotlib inline
print mpl.get_backend()
# This prints "module://ipykernel.pylab.backend_inline", because inline has been set
set_default()
print mpl.get_backend()
# This prints "agg", because this is the default backend reset by setting the empty rc file
plt.plot()
# Here, no plot is shown because agg (a non interactive backend) is used.
Until here no supprise.
Now the second case.
import matplotlib as mpl
def set_default():
mpl.rc_file('matplotlibrc.txt') # this is an empty file
import matplotlib.pyplot as plt
print mpl.get_backend()
# This prints u'TkAgg' (in my case) the default backend in use, same as above
%matplotlib inline
print mpl.get_backend()
# This prints "module://ipykernel.pylab.backend_inline", because inline has been set
plt.plot()
# This shows the inline plot, because the inline backend is active.
set_default()
print mpl.get_backend()
# This prints "agg", because this is the default backend reset by setting the new empty rc file
plt.plot()
# Here comes the supprise: Although "agg" is the backend, still, an inline plot is shown.
# This is due to the inline backend being the one registered in pyplot
# when doing the first plot. It cannot be changed afterwards.
The main point is, you may still change the backend, until the first plot is produced, not after.
The same argument goes for the figure size. The default matplotlib figure size is (6.4,4.8), while the one being set with the inline backend is (6.0,4.0). Also the figure dpi is different, it is 100 in the default rcParams, but 72. in the inline configuration. This makes the plot appear much smaller.
Now to the actual problem. I suppose the use of a stylesheet is meant here to set some styles for plots, not to change the backend. Hence you would rather only set the style from the rc file. This can be done in the usual way,using matplotlib.style.use
def set_default():
mpl.style.use('matplotlibrc.txt')
When this is used, it will not overwrite the backend in use, but only update those parameters, specified in the file itself.

Python Matplotlib: Clear figure when figure window is not open

I'm working with matplotlib plotting and use ioff() to switch interactive mode off to suppress the automatic opening of the plotting window on figrue creation. I want to have full control over the figure and only see it when explicitely using the show() command.
Now apparently the built-in commands to clear figures and axes do not work properly anymore.
Example:
import numpy as np
import matplotlib.pyplot as mpp
class PlotTest:
def __init__(self,nx=1,ny=1):
# Switch off interactive mode:
mpp.ioff()
# Create Figure and Axes:
self.createFigure(nx, ny)
def createFigure(self,nx=1,ny=1):
self.fig, self.axes = mpp.subplots(nx,ny)
if nx*ny == 1:
self.axes = np.array([self.axes])
def linePlot(self):
X = np.linspace(0,20,21)
Y = np.random.rand(21)
self.axes[0].plot(X,Y)
P = PlotTest()
P.linePlot()
P.fig.show()
Now I was thinking I could use P.fig.clear() any time to simply clear P.fig, but apparently that's not the case.
Writing P.fig.clear() directly into the script and execute it together it works and all I see is an empty figure. However that's rather pointless as I never get to see the actual plot like that.
Doing P.fig.clear() manually in the console does not do anything, regardless if the plot window is open or not, all other possible commands fail as well:
P.fig.clf()
P.axes[0].clear()
P.axes[0].cla()
mpp.clf()
mpp.cla()
mpp.close(P.fig)
Wrapping the command into a class method doesn't work either:
def clearFig(self):
self.fig.clear()
EDIT ================
After a clear() fig.axes is empty, yet show() still shows the old plot with the axes still being plotted.
/EDIT ================
Is it because I switched off interactive mode?
If you add a call to plt.draw() after P.fig.clear() it clears the figure. From the docs,
This is used in interactive mode to update a figure that has been altered, but not automatically re-drawn. This should be only rarely needed, but there may be ways to modify the state of a figure with out marking it as stale. Please report these cases as bugs.
I guess this is not a bug as you have switched off interactive mode so it is now your responsibility to explicitly redraw when you want to.
You can also use P.fig.canvas.draw_idle() which could be wrapper in the class as clearFigure method.

Categories