77
88import matplotlib
99from matplotlib .backends .backend_agg import new_figure_manager , FigureCanvasAgg # analysis: ignore
10+ from matplotlib import colors
1011from matplotlib ._pylab_helpers import Gcf
1112
1213from IPython .core .getipython import get_ipython
@@ -33,7 +34,10 @@ def show(close=None, block=None):
3334 close = InlineBackend .instance ().close_figures
3435 try :
3536 for figure_manager in Gcf .get_all_fig_managers ():
36- display (figure_manager .canvas .figure )
37+ display (
38+ figure_manager .canvas .figure ,
39+ metadata = _fetch_figure_metadata (figure_manager .canvas .figure )
40+ )
3741 finally :
3842 show ._to_draw = []
3943 # only call close('all') if any to close
@@ -72,7 +76,7 @@ def draw_if_interactive():
7276
7377 if not hasattr (fig , 'show' ):
7478 # Queue up `fig` for display
75- fig .show = lambda * a : display (fig )
79+ fig .show = lambda * a : display (fig , metadata = _fetch_figure_metadata ( fig ) )
7680
7781 # If matplotlib was manually set to non-interactive mode, this function
7882 # should be a no-op (otherwise we'll generate duplicate plots, since a user
@@ -124,7 +128,7 @@ def flush_figures():
124128 active = set ([fm .canvas .figure for fm in Gcf .get_all_fig_managers ()])
125129 for fig in [ fig for fig in show ._to_draw if fig in active ]:
126130 try :
127- display (fig )
131+ display (fig , metadata = _fetch_figure_metadata ( fig ) )
128132 except Exception as e :
129133 # safely show traceback if in IPython, else raise
130134 ip = get_ipython ()
@@ -163,3 +167,30 @@ def configure_once(*args):
163167 ip .events .register ('post_run_cell' , configure_once )
164168
165169_enable_matplotlib_integration ()
170+
171+ def _fetch_figure_metadata (fig ):
172+ """Get some metadata to help with displaying a figure."""
173+ # determine if a background is needed for legibility
174+ if _is_transparent (fig .get_facecolor ()):
175+ # the background is transparent
176+ ticksLight = _is_light ([label .get_color ()
177+ for axes in fig .axes
178+ for axis in (axes .xaxis , axes .yaxis )
179+ for label in axis .get_ticklabels ()])
180+ if ticksLight .size and (ticksLight == ticksLight [0 ]).all ():
181+ # there are one or more tick labels, all with the same lightness
182+ return {'needs_background' : 'dark' if ticksLight [0 ] else 'light' }
183+
184+ return None
185+
186+ def _is_light (color ):
187+ """Determines if a color (or each of a sequence of colors) is light (as
188+ opposed to dark). Based on ITU BT.601 luminance formula (see
189+ https://stackoverflow.com/a/596241)."""
190+ rgbaArr = colors .to_rgba_array (color )
191+ return rgbaArr [:,:3 ].dot ((.299 , .587 , .114 )) > .5
192+
193+ def _is_transparent (color ):
194+ """Determine transparency from alpha."""
195+ rgba = colors .to_rgba (color )
196+ return rgba [3 ] < .5
0 commit comments