Skip to content

Commit bfc7093

Browse files
committed
By default, don't change the figure face/edgecolor on savefig().
This seems to repeatedly confuse users.
1 parent 59762d4 commit bfc7093

File tree

7 files changed

+65
-65
lines changed

7 files changed

+65
-65
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
:rc:`savefig.facecolor` and :rc:`savefig.edgecolor` now default to "auto"
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
This newly allowed value for :rc:`savefig.facecolor` and :rc:`savefig.edgecolor`,
5+
as well as the *facecolor* and *edgecolor* parameters to `.Figure.savefig`, means
6+
"use whatever facecolor and edgecolor the figure current has".
7+
8+
`.FigureCanvasPS.print_ps` and `.FigureCanvasPS.print_eps` no longer set the figure *facecolor* and *edgecolor*
9+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10+
11+
Modification of the figure facecolor and edgecolor are already handled
12+
by `.FigureCanvasBase.print_figure` (which is in charge of calling
13+
`.FigureCanvasPS.print_ps` or `.FigureCanvasPS.print_eps`). This
14+
behavior is consistent with the other backend printing methods
15+
(`.FigureCanvasPdf.print_pdf`, `.FigureCanvasSVG.print_svg`, etc.)

lib/matplotlib/backend_bases.py

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
The base class for the messaging area.
3333
"""
3434

35-
from contextlib import contextmanager
35+
from contextlib import contextmanager, ExitStack
3636
from enum import IntEnum
3737
import functools
3838
import importlib
@@ -2002,32 +2002,35 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
20022002
can also be a file object on image backends
20032003
20042004
orientation : {'landscape', 'portrait'}, optional
2005-
only currently applies to PostScript printing.
2005+
Only currently applies to PostScript printing.
20062006
20072007
dpi : scalar, optional
2008-
the dots per inch to save the figure in; if None, use savefig.dpi
2008+
The dots per inch to save the figure in; if None, use
2009+
:rc:`savefig.dpi`.
20092010
2010-
facecolor : color or None, optional
2011-
the facecolor of the figure; if None, defaults to savefig.facecolor
2011+
facecolor : color or 'auto' or None, optional
2012+
The facecolor of the figure. If 'auto', use the current figure
2013+
facecolor. If None, use :rc:`savefig.facecolor`.
20122014
2013-
edgecolor : color or None, optional
2014-
the edgecolor of the figure; if None, defaults to savefig.edgecolor
2015+
edgecolor : color or 'auto' or None, optional
2016+
The edgecolor of the figure. If 'auto', use the current figure
2017+
edgecolor. If None, use :rc:`savefig.edgecolor`.
20152018
20162019
format : str, optional
2017-
when set, forcibly set the file format to save to
2020+
When set, forcibly set the file format to save to.
20182021
20192022
bbox_inches : str or `~matplotlib.transforms.Bbox`, optional
2020-
Bbox in inches. Only the given portion of the figure is
2021-
saved. If 'tight', try to figure out the tight bbox of
2022-
the figure. If None, use savefig.bbox
2023+
Bbox in inches. Only the given portion of the figure is saved. If
2024+
'tight', try to figure out the tight bbox of the figure. If None,
2025+
use :rc:`savefig.bbox`.
20232026
20242027
pad_inches : scalar, optional
2025-
Amount of padding around the figure when bbox_inches is
2026-
'tight'. If None, use savefig.pad_inches
2028+
Amount of padding around the figure when bbox_inches is 'tight'. If
2029+
None, use :rc:`savefig.pad_inches`.
20272030
20282031
bbox_extra_artists : list of `~matplotlib.artist.Artist`, optional
2029-
A list of extra artists that will be considered when the
2030-
tight bbox is calculated.
2032+
A list of extra artists that will be considered when the tight bbox
2033+
is calculated.
20312034
20322035
"""
20332036
if format is None:
@@ -2051,27 +2054,29 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
20512054
if dpi == 'figure':
20522055
dpi = getattr(self.figure, '_original_dpi', self.figure.dpi)
20532056

2054-
# Remove the figure manager, if any, to avoid resizing the GUI widget.
2055-
# Some code (e.g. Figure.show) differentiates between having *no*
2056-
# manager and a *None* manager, which should be fixed at some point,
2057-
# but this should be fine.
2058-
with cbook._setattr_cm(self, _is_saving=True, manager=None), \
2059-
cbook._setattr_cm(self.figure, dpi=dpi):
2060-
2057+
with ExitStack() as stack:
2058+
# Remove the figure manager, if any, to avoid resizing the GUI
2059+
# widget. Some code (e.g. Figure.show) differentiates between
2060+
# having *no* manager and a *None* manager, which should be fixed
2061+
# at some point, but this should be fine.
2062+
stack.enter_context(
2063+
cbook._setattr_cm(self, _is_saving=True, manager=None))
2064+
stack.enter_context(cbook._setattr_cm(self.figure, dpi=dpi))
20612065
if facecolor is None:
20622066
facecolor = rcParams['savefig.facecolor']
2067+
if not cbook._str_equal(facecolor, 'auto'):
2068+
stack.callback(
2069+
self.figure.set_facecolor, self.figure.get_facecolor())
2070+
self.figure.set_facecolor(facecolor)
20632071
if edgecolor is None:
20642072
edgecolor = rcParams['savefig.edgecolor']
2065-
2066-
origfacecolor = self.figure.get_facecolor()
2067-
origedgecolor = self.figure.get_edgecolor()
2068-
2069-
self.figure.set_facecolor(facecolor)
2070-
self.figure.set_edgecolor(edgecolor)
2073+
if not cbook._str_equal(edgecolor, 'auto'):
2074+
stack.callback(
2075+
self.figure.set_edgecolor, self.figure.get_edgecolor())
2076+
self.figure.set_edgecolor(edgecolor)
20712077

20722078
if bbox_inches is None:
20732079
bbox_inches = rcParams['savefig.bbox']
2074-
20752080
if bbox_inches:
20762081
if bbox_inches == "tight":
20772082
renderer = _get_renderer(
@@ -2109,8 +2114,6 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
21092114
if bbox_inches and restore_bbox:
21102115
restore_bbox()
21112116

2112-
self.figure.set_facecolor(origfacecolor)
2113-
self.figure.set_edgecolor(origedgecolor)
21142117
self.figure.set_canvas(self)
21152118
return result
21162119

lib/matplotlib/backends/backend_ps.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -916,11 +916,6 @@ def _print_figure(
916916
bbox = (llx, lly, urx, ury)
917917

918918
# generate PostScript code for the figure and store it in a string
919-
origfacecolor = self.figure.get_facecolor()
920-
origedgecolor = self.figure.get_edgecolor()
921-
self.figure.set_facecolor(facecolor)
922-
self.figure.set_edgecolor(edgecolor)
923-
924919
if dryrun:
925920
class NullWriter:
926921
def write(self, *args, **kwargs):
@@ -941,9 +936,6 @@ def write(self, *args, **kwargs):
941936
if dryrun: # return immediately if dryrun (tightbbox=True)
942937
return
943938

944-
self.figure.set_facecolor(origfacecolor)
945-
self.figure.set_edgecolor(origedgecolor)
946-
947939
# check for custom metadata
948940
if metadata is not None and 'Creator' in metadata:
949941
creator_str = metadata['Creator']
@@ -1113,11 +1105,6 @@ def _print_figure_tex(
11131105
bbox = (llx, lly, urx, ury)
11141106

11151107
# generate PostScript code for the figure and store it in a string
1116-
origfacecolor = self.figure.get_facecolor()
1117-
origedgecolor = self.figure.get_edgecolor()
1118-
self.figure.set_facecolor(facecolor)
1119-
self.figure.set_edgecolor(edgecolor)
1120-
11211108
if dryrun:
11221109
class NullWriter:
11231110
def write(self, *args, **kwargs):
@@ -1138,9 +1125,6 @@ def write(self, *args, **kwargs):
11381125
if dryrun: # return immediately if dryrun (tightbbox=True)
11391126
return
11401127

1141-
self.figure.set_facecolor(origfacecolor)
1142-
self.figure.set_edgecolor(origedgecolor)
1143-
11441128
# check for custom metadata
11451129
if metadata is not None and 'Creator' in metadata:
11461130
creator_str = metadata['Creator']

lib/matplotlib/figure.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,13 +2112,13 @@ def savefig(self, fname, *, transparent=None, **kwargs):
21122112
progressive JPEG file. Applicable only if *format* is jpg or
21132113
jpeg, ignored otherwise. Is *False* by default.
21142114
2115-
facecolor : color or None, optional
2116-
The facecolor of the figure; if *None*, defaults to
2117-
:rc:`savefig.facecolor`.
2115+
facecolor : color or 'auto' or None, optional
2116+
The facecolor of the figure. If 'auto', use the current figure
2117+
facecolor. If None, use :rc:`savefig.facecolor`.
21182118
2119-
edgecolor : color or None, optional
2120-
The edgecolor of the figure; if *None*, defaults to
2121-
:rc:`savefig.edgecolor`
2119+
edgecolor : color or 'auto' or None, optional
2120+
The edgecolor of the figure. If 'auto', use the current figure
2121+
edgecolor. If None, use :rc:`savefig.edgecolor`.
21222122
21232123
orientation : {'landscape', 'portrait'}
21242124
Currently only supported by the postscript backend.
@@ -2193,9 +2193,6 @@ def savefig(self, fname, *, transparent=None, **kwargs):
21932193
patch.get_edgecolor()))
21942194
patch.set_facecolor('none')
21952195
patch.set_edgecolor('none')
2196-
else:
2197-
kwargs.setdefault('facecolor', rcParams['savefig.facecolor'])
2198-
kwargs.setdefault('edgecolor', rcParams['savefig.edgecolor'])
21992196

22002197
if frameon:
22012198
original_frameon = self.patch.get_visible()

lib/matplotlib/image.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,9 +1547,10 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
15471547
pil_kwargs["pnginfo"] = pnginfo
15481548
if format in ["jpg", "jpeg"]:
15491549
format = "jpeg" # Pillow doesn't recognize "jpg".
1550-
color = tuple(
1551-
int(x * 255)
1552-
for x in mcolors.to_rgb(rcParams["savefig.facecolor"]))
1550+
facecolor = rcParams["savefig.facecolor"]
1551+
if cbook._str_equal(facecolor, "auto"):
1552+
facecolor = rcParams["figure.facecolor"]
1553+
color = tuple(int(x * 255) for x in mcolors.to_rgb(facecolor))
15531554
background = Image.new("RGB", pil_shape, color)
15541555
background.paste(image, image)
15551556
image = background

lib/matplotlib/rcsetup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,13 @@ def validator(s):
297297

298298
def validate_color_or_inherit(s):
299299
"""Return a valid color arg."""
300-
if s == 'inherit':
300+
if cbook._str_equal(s, 'inherit'):
301301
return s
302302
return validate_color(s)
303303

304304

305305
def validate_color_or_auto(s):
306-
if s == 'auto':
306+
if cbook._str_equal(s, 'auto'):
307307
return s
308308
return validate_color(s)
309309

@@ -1371,8 +1371,8 @@ def _validate_linestyle(ls):
13711371

13721372
## Saving figure's properties
13731373
'savefig.dpi': ['figure', validate_dpi], # DPI
1374-
'savefig.facecolor': ['white', validate_color],
1375-
'savefig.edgecolor': ['white', validate_color],
1374+
'savefig.facecolor': ['auto', validate_color_or_auto],
1375+
'savefig.edgecolor': ['auto', validate_color_or_auto],
13761376
'savefig.frameon': [True, validate_bool],
13771377
'savefig.orientation': ['portrait', validate_orientation],
13781378
'savefig.jpeg_quality': [95, validate_int],

matplotlibrc.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,8 @@
642642
## e.g., you may want a higher resolution, or to make the figure
643643
## background white
644644
#savefig.dpi : figure ## figure dots per inch or 'figure'
645-
#savefig.facecolor : white ## figure facecolor when saving
646-
#savefig.edgecolor : white ## figure edgecolor when saving
645+
#savefig.facecolor : auto ## figure facecolor when saving
646+
#savefig.edgecolor : auto ## figure edgecolor when saving
647647
#savefig.format : png ## {png, ps, pdf, svg}
648648
#savefig.bbox : standard ## {tight, standard}
649649
## 'tight' is incompatible with pipe-based animation

0 commit comments

Comments
 (0)