Inconsistent font settings when changing style context
utf opened this issue · comments
Bug report
Bug summary
When using style context manager to apply font styles the behaviour is not predictable. Below are two examples. Overall it seems like the styling is being defined when the axis is created, and not refreshed when the style is tweaked.
Example 1
If the axis is created outside the style context, then no font updates are applied when entering and saving the figure in the style context.
Code for reproduction
import matplotlib
import matplotlib.pyplot as plt
font_style = {'font.sans-serif': 'Bitstream Vera Sans',
'font.size': 22}
fig, ax = plt.subplots()
with matplotlib.pyplot.style.context(font_style):
print(matplotlib.rcParams['font.sans-serif'])
print(matplotlib.rcParams['font.size'])
ax.set_xlabel('test')
ax.set_ylabel('test')
plt.savefig('example_1.png', bbox_inches='tight')
Actual outcome
Console:
['Bitstream Vera Sans']
22.0
Expected outcome
The font size should be bigger and be Bitstream Vera Sans.
Example 2
Creating the figure in the context, then exiting the context and writing a new piece of text (using different settings) does not apply the correct font settings.
Code for reproduction
import matplotlib
import matplotlib.pyplot as plt
font_style = {'font.sans-serif': 'Bitstream Vera Sans',
'font.size': 22}
with matplotlib.pyplot.style.context(font_style):
fig, ax = plt.subplots()
print(matplotlib.rcParams['font.sans-serif'])
print(matplotlib.rcParams['font.size'])
ax.set_xlabel('test')
print(matplotlib.rcParams['font.sans-serif'])
print(matplotlib.rcParams['font.size'])
ax.set_ylabel('test')
plt.savefig('example_2.png', bbox_inches='tight')
Actual outcome
Console;
['Bitstream Vera Sans']
22.0
['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif']
10.0
Expected outcome
One axis label should be size 22 Bitstream Vera Sans, the other axis label should be size 10 DejaVu Sans.
Matplotlib version
- Operating system: Bash on windows
- Matplotlib version: 2.1.2
- Matplotlib backend: TkAgg
- Python version: 3.5.2
Matplotlib was installed via pip.
Some more data points: here's a little experiment on Linux Mint with Matplotlib 2.2.2 using iPython 6.1.0 with the %matplotlib
magic and TkAgg backend.
The new font is applied correctly in the exported PNG, but not in the floating figure. Other styling (dark background, green ticks) are applied correctly. Without using the %matplotlib
magic and calling plt.show()
explicitly, the font displays correctly. Using matplotlib.style.use()
instead of the context manager also works correctly.
Yeah, unfortunately the text object that will contain the labels is instantiated when the axes is created. set_xlabel
currently doesn't go back and check rcParams to update the font properties.
I think it could be modified to check the rcParams. But we get into a lot of other issues with consistency. I think a lot of matplotlib depends on the idea that the rcParams aren't changing all the time, though the use of a context manager would seem to be-lie that.
At the very least, we need to be clearer in the documentation about what scope the context manager is meant to operate on: i.e. per-figure, per-axes, per-artist?
The use case we had in mind when encountering this was allowing the use of minimal style sheets to adjust different Axes within a tiled set of plots, e.g. as a way of tweaking font sizes and line widths where specialised plots have different needs. Should that be considered "un-matplotlib-ic"?
@ajjackson Not necessarily - just not how it works right now. When you call subplots
you create all the axes, rcParams
is checked, and the font properties set.
If you wanted to use gridspec and add the axes individually, my guess is some could be added in context, but I've not tested:
gs = gridspec.GridSpec(1, 2)
with matplotlib.pyplot.style.context(font_style1):
fig.add_subplot(gs[0, 0])
with matplotlib.pyplot.style.context(font_style2):
fig.add_subplot(gs[0, 1])
Its possible for set_xlabel
to check the rcparam when its called, it just doesn't.
I'm going to close as won't fix. The current behaviour is the simplest, and controlling font properties can be done when making the labels..
It would be nice if plt.style.context
or sns.axes_styles
had a little note that they are broken for setting fonts.