diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/matplotlib-inline | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/matplotlib-inline')
-rw-r--r-- | contrib/python/matplotlib-inline/.dist-info/METADATA | 26 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/.dist-info/top_level.txt | 2 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/LICENSE | 58 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/README.md | 60 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/matplotlib_inline/backend_inline.py | 612 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/matplotlib_inline/config.py | 214 | ||||
-rw-r--r-- | contrib/python/matplotlib-inline/ya.make | 62 |
7 files changed, 517 insertions, 517 deletions
diff --git a/contrib/python/matplotlib-inline/.dist-info/METADATA b/contrib/python/matplotlib-inline/.dist-info/METADATA index f328e06e84..4920c61625 100644 --- a/contrib/python/matplotlib-inline/.dist-info/METADATA +++ b/contrib/python/matplotlib-inline/.dist-info/METADATA @@ -1,16 +1,16 @@ -Metadata-Version: 2.1 -Name: matplotlib-inline +Metadata-Version: 2.1 +Name: matplotlib-inline Version: 0.1.3 -Summary: Inline Matplotlib backend for Jupyter +Summary: Inline Matplotlib backend for Jupyter Home-page: https://github.com/ipython/matplotlib-inline -Author: IPython Development Team -Author-email: ipython-dev@scipy.org -License: BSD 3-Clause -Keywords: python,ipython,matplotlib,jupyter -Platform: UNKNOWN -Requires-Python: >=3.5 +Author: IPython Development Team +Author-email: ipython-dev@scipy.org +License: BSD 3-Clause +Keywords: python,ipython,matplotlib,jupyter +Platform: UNKNOWN +Requires-Python: >=3.5 License-File: LICENSE -Requires-Dist: traitlets - -UNKNOWN - +Requires-Dist: traitlets + +UNKNOWN + diff --git a/contrib/python/matplotlib-inline/.dist-info/top_level.txt b/contrib/python/matplotlib-inline/.dist-info/top_level.txt index 4b061e8006..1b3ff3d6a1 100644 --- a/contrib/python/matplotlib-inline/.dist-info/top_level.txt +++ b/contrib/python/matplotlib-inline/.dist-info/top_level.txt @@ -1 +1 @@ -matplotlib_inline +matplotlib_inline diff --git a/contrib/python/matplotlib-inline/LICENSE b/contrib/python/matplotlib-inline/LICENSE index 1619c6dc03..1b6bb1ca62 100644 --- a/contrib/python/matplotlib-inline/LICENSE +++ b/contrib/python/matplotlib-inline/LICENSE @@ -1,29 +1,29 @@ -BSD 3-Clause License - -Copyright (c) 2019, -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +BSD 3-Clause License + +Copyright (c) 2019, +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/python/matplotlib-inline/README.md b/contrib/python/matplotlib-inline/README.md index 9ef91180b1..d867a10191 100644 --- a/contrib/python/matplotlib-inline/README.md +++ b/contrib/python/matplotlib-inline/README.md @@ -1,30 +1,30 @@ -# Matplotlib Inline Back-end for IPython and Jupyter - -## Installation - -With conda: - -```bash -conda install -c conda-forge notebook matplotlib -``` - -With pip: - -```bash -pip install notebook matplotlib -``` - -## Usage - -This package is included in IPython and can be used in a Jupyter Notebook: - -```python -%matplotlib inline - -import matplotlib.pyplot as plt -import numpy as np - -x = np.linspace(0, 3*np.pi, 500) -plt.plot(x, np.sin(x**2)) -plt.title('A simple chirp'); -``` +# Matplotlib Inline Back-end for IPython and Jupyter + +## Installation + +With conda: + +```bash +conda install -c conda-forge notebook matplotlib +``` + +With pip: + +```bash +pip install notebook matplotlib +``` + +## Usage + +This package is included in IPython and can be used in a Jupyter Notebook: + +```python +%matplotlib inline + +import matplotlib.pyplot as plt +import numpy as np + +x = np.linspace(0, 3*np.pi, 500) +plt.plot(x, np.sin(x**2)) +plt.title('A simple chirp'); +``` diff --git a/contrib/python/matplotlib-inline/matplotlib_inline/backend_inline.py b/contrib/python/matplotlib-inline/matplotlib_inline/backend_inline.py index ca2e003186..1e3431fc0f 100644 --- a/contrib/python/matplotlib-inline/matplotlib_inline/backend_inline.py +++ b/contrib/python/matplotlib-inline/matplotlib_inline/backend_inline.py @@ -1,306 +1,306 @@ -"""A matplotlib backend for publishing figures via display_data""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the BSD 3-Clause License. - -import matplotlib -from matplotlib.backends.backend_agg import ( # noqa - new_figure_manager, - FigureCanvasAgg, - new_figure_manager_given_figure, -) -from matplotlib import colors -from matplotlib._pylab_helpers import Gcf - -from IPython.core.interactiveshell import InteractiveShell -from IPython.core.getipython import get_ipython -from IPython.core.pylabtools import select_figure_formats -from IPython.display import display - -from .config import InlineBackend - - -def show(close=None, block=None): - """Show all figures as SVG/PNG payloads sent to the IPython clients. - - Parameters - ---------- - close : bool, optional - If true, a ``plt.close('all')`` call is automatically issued after - sending all the figures. If this is set, the figures will entirely - removed from the internal list of figures. - block : Not used. - The `block` parameter is a Matplotlib experimental parameter. - We accept it in the function signature for compatibility with other - backends. - """ - if close is None: - close = InlineBackend.instance().close_figures - try: - for figure_manager in Gcf.get_all_fig_managers(): - display( - figure_manager.canvas.figure, - metadata=_fetch_figure_metadata(figure_manager.canvas.figure) - ) - finally: - show._to_draw = [] - # only call close('all') if any to close - # close triggers gc.collect, which can be slow - if close and Gcf.get_all_fig_managers(): - matplotlib.pyplot.close('all') - - -# This flag will be reset by draw_if_interactive when called -show._draw_called = False -# list of figures to draw when flush_figures is called -show._to_draw = [] - - -def draw_if_interactive(): - """ - Is called after every pylab drawing command - """ - # signal that the current active figure should be sent at the end of - # execution. Also sets the _draw_called flag, signaling that there will be - # something to send. At the end of the code execution, a separate call to - # flush_figures() will act upon these values - manager = Gcf.get_active() - if manager is None: - return - fig = manager.canvas.figure - - # Hack: matplotlib FigureManager objects in interacive backends (at least - # in some of them) monkeypatch the figure object and add a .show() method - # to it. This applies the same monkeypatch in order to support user code - # that might expect `.show()` to be part of the official API of figure - # objects. - # For further reference: - # https://github.com/ipython/ipython/issues/1612 - # https://github.com/matplotlib/matplotlib/issues/835 - - if not hasattr(fig, 'show'): - # Queue up `fig` for display - fig.show = lambda *a: display(fig, metadata=_fetch_figure_metadata(fig)) - - # If matplotlib was manually set to non-interactive mode, this function - # should be a no-op (otherwise we'll generate duplicate plots, since a user - # who set ioff() manually expects to make separate draw/show calls). - if not matplotlib.is_interactive(): - return - - # ensure current figure will be drawn, and each subsequent call - # of draw_if_interactive() moves the active figure to ensure it is - # drawn last - try: - show._to_draw.remove(fig) - except ValueError: - # ensure it only appears in the draw list once - pass - # Queue up the figure for drawing in next show() call - show._to_draw.append(fig) - show._draw_called = True - - -def flush_figures(): - """Send all figures that changed - - This is meant to be called automatically and will call show() if, during - prior code execution, there had been any calls to draw_if_interactive. - - This function is meant to be used as a post_execute callback in IPython, - so user-caused errors are handled with showtraceback() instead of being - allowed to raise. If this function is not called from within IPython, - then these exceptions will raise. - """ - if not show._draw_called: - return - - if InlineBackend.instance().close_figures: - # ignore the tracking, just draw and close all figures - try: - return show(True) - except Exception as e: - # safely show traceback if in IPython, else raise - ip = get_ipython() - if ip is None: - raise e - else: - ip.showtraceback() - return - try: - # exclude any figures that were closed: - active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()]) - for fig in [fig for fig in show._to_draw if fig in active]: - try: - display(fig, metadata=_fetch_figure_metadata(fig)) - except Exception as e: - # safely show traceback if in IPython, else raise - ip = get_ipython() - if ip is None: - raise e - else: - ip.showtraceback() - return - finally: - # clear flags for next round - show._to_draw = [] - show._draw_called = False - - -# Changes to matplotlib in version 1.2 requires a mpl backend to supply a default -# figurecanvas. This is set here to a Agg canvas -# See https://github.com/matplotlib/matplotlib/pull/1125 -FigureCanvas = FigureCanvasAgg - - -def configure_inline_support(shell, backend): - """Configure an IPython shell object for matplotlib use. - - Parameters - ---------- - shell : InteractiveShell instance - - backend : matplotlib backend - """ - # If using our svg payload backend, register the post-execution - # function that will pick up the results for display. This can only be - # done with access to the real shell object. - - cfg = InlineBackend.instance(parent=shell) - cfg.shell = shell - if cfg not in shell.configurables: - shell.configurables.append(cfg) - - if backend == 'module://matplotlib_inline.backend_inline': - shell.events.register('post_execute', flush_figures) - - # Save rcParams that will be overwrittern - shell._saved_rcParams = {} - for k in cfg.rc: - shell._saved_rcParams[k] = matplotlib.rcParams[k] - # load inline_rc - matplotlib.rcParams.update(cfg.rc) - new_backend_name = "inline" - else: - try: - shell.events.unregister('post_execute', flush_figures) - except ValueError: - pass - if hasattr(shell, '_saved_rcParams'): - matplotlib.rcParams.update(shell._saved_rcParams) - del shell._saved_rcParams - new_backend_name = "other" - - # only enable the formats once -> don't change the enabled formats (which the user may - # has changed) when getting another "%matplotlib inline" call. - # See https://github.com/ipython/ipykernel/issues/29 - cur_backend = getattr(configure_inline_support, "current_backend", "unset") - if new_backend_name != cur_backend: - # Setup the default figure format - select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs) - configure_inline_support.current_backend = new_backend_name - - -def _enable_matplotlib_integration(): - """Enable extra IPython matplotlib integration when we are loaded as the matplotlib backend.""" - from matplotlib import get_backend - ip = get_ipython() - backend = get_backend() - if ip and backend == 'module://%s' % __name__: - from IPython.core.pylabtools import activate_matplotlib - try: - activate_matplotlib(backend) - configure_inline_support(ip, backend) - except (ImportError, AttributeError): - # bugs may cause a circular import on Python 2 - def configure_once(*args): - activate_matplotlib(backend) - configure_inline_support(ip, backend) - ip.events.unregister('post_run_cell', configure_once) - ip.events.register('post_run_cell', configure_once) - - -_enable_matplotlib_integration() - - -def _fetch_figure_metadata(fig): - """Get some metadata to help with displaying a figure.""" - # determine if a background is needed for legibility - if _is_transparent(fig.get_facecolor()): - # the background is transparent - ticksLight = _is_light([label.get_color() - for axes in fig.axes - for axis in (axes.xaxis, axes.yaxis) - for label in axis.get_ticklabels()]) - if ticksLight.size and (ticksLight == ticksLight[0]).all(): - # there are one or more tick labels, all with the same lightness - return {'needs_background': 'dark' if ticksLight[0] else 'light'} - - return None - - -def _is_light(color): - """Determines if a color (or each of a sequence of colors) is light (as - opposed to dark). Based on ITU BT.601 luminance formula (see - https://stackoverflow.com/a/596241).""" - rgbaArr = colors.to_rgba_array(color) - return rgbaArr[:, :3].dot((.299, .587, .114)) > .5 - - -def _is_transparent(color): - """Determine transparency from alpha.""" - rgba = colors.to_rgba(color) - return rgba[3] < .5 - - -def set_matplotlib_formats(*formats, **kwargs): - """Select figure formats for the inline backend. Optionally pass quality for JPEG. - - For example, this enables PNG and JPEG output with a JPEG quality of 90%:: - - In [1]: set_matplotlib_formats('png', 'jpeg', quality=90) - - To set this in your config files use the following:: - - c.InlineBackend.figure_formats = {'png', 'jpeg'} - c.InlineBackend.print_figure_kwargs.update({'quality' : 90}) - - Parameters - ---------- - *formats : strs - One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. - **kwargs - Keyword args will be relayed to ``figure.canvas.print_figure``. - """ - # build kwargs, starting with InlineBackend config - cfg = InlineBackend.instance() - kw = {} - kw.update(cfg.print_figure_kwargs) - kw.update(**kwargs) - shell = InteractiveShell.instance() - select_figure_formats(shell, formats, **kw) - - -def set_matplotlib_close(close=True): - """Set whether the inline backend closes all figures automatically or not. - - By default, the inline backend used in the IPython Notebook will close all - matplotlib figures automatically after each cell is run. This means that - plots in different cells won't interfere. Sometimes, you may want to make - a plot in one cell and then refine it in later cells. This can be accomplished - by:: - - In [1]: set_matplotlib_close(False) - - To set this in your config files use the following:: - - c.InlineBackend.close_figures = False - - Parameters - ---------- - close : bool - Should all matplotlib figures be automatically closed after each cell is - run? - """ - cfg = InlineBackend.instance() - cfg.close_figures = close +"""A matplotlib backend for publishing figures via display_data""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the BSD 3-Clause License. + +import matplotlib +from matplotlib.backends.backend_agg import ( # noqa + new_figure_manager, + FigureCanvasAgg, + new_figure_manager_given_figure, +) +from matplotlib import colors +from matplotlib._pylab_helpers import Gcf + +from IPython.core.interactiveshell import InteractiveShell +from IPython.core.getipython import get_ipython +from IPython.core.pylabtools import select_figure_formats +from IPython.display import display + +from .config import InlineBackend + + +def show(close=None, block=None): + """Show all figures as SVG/PNG payloads sent to the IPython clients. + + Parameters + ---------- + close : bool, optional + If true, a ``plt.close('all')`` call is automatically issued after + sending all the figures. If this is set, the figures will entirely + removed from the internal list of figures. + block : Not used. + The `block` parameter is a Matplotlib experimental parameter. + We accept it in the function signature for compatibility with other + backends. + """ + if close is None: + close = InlineBackend.instance().close_figures + try: + for figure_manager in Gcf.get_all_fig_managers(): + display( + figure_manager.canvas.figure, + metadata=_fetch_figure_metadata(figure_manager.canvas.figure) + ) + finally: + show._to_draw = [] + # only call close('all') if any to close + # close triggers gc.collect, which can be slow + if close and Gcf.get_all_fig_managers(): + matplotlib.pyplot.close('all') + + +# This flag will be reset by draw_if_interactive when called +show._draw_called = False +# list of figures to draw when flush_figures is called +show._to_draw = [] + + +def draw_if_interactive(): + """ + Is called after every pylab drawing command + """ + # signal that the current active figure should be sent at the end of + # execution. Also sets the _draw_called flag, signaling that there will be + # something to send. At the end of the code execution, a separate call to + # flush_figures() will act upon these values + manager = Gcf.get_active() + if manager is None: + return + fig = manager.canvas.figure + + # Hack: matplotlib FigureManager objects in interacive backends (at least + # in some of them) monkeypatch the figure object and add a .show() method + # to it. This applies the same monkeypatch in order to support user code + # that might expect `.show()` to be part of the official API of figure + # objects. + # For further reference: + # https://github.com/ipython/ipython/issues/1612 + # https://github.com/matplotlib/matplotlib/issues/835 + + if not hasattr(fig, 'show'): + # Queue up `fig` for display + fig.show = lambda *a: display(fig, metadata=_fetch_figure_metadata(fig)) + + # If matplotlib was manually set to non-interactive mode, this function + # should be a no-op (otherwise we'll generate duplicate plots, since a user + # who set ioff() manually expects to make separate draw/show calls). + if not matplotlib.is_interactive(): + return + + # ensure current figure will be drawn, and each subsequent call + # of draw_if_interactive() moves the active figure to ensure it is + # drawn last + try: + show._to_draw.remove(fig) + except ValueError: + # ensure it only appears in the draw list once + pass + # Queue up the figure for drawing in next show() call + show._to_draw.append(fig) + show._draw_called = True + + +def flush_figures(): + """Send all figures that changed + + This is meant to be called automatically and will call show() if, during + prior code execution, there had been any calls to draw_if_interactive. + + This function is meant to be used as a post_execute callback in IPython, + so user-caused errors are handled with showtraceback() instead of being + allowed to raise. If this function is not called from within IPython, + then these exceptions will raise. + """ + if not show._draw_called: + return + + if InlineBackend.instance().close_figures: + # ignore the tracking, just draw and close all figures + try: + return show(True) + except Exception as e: + # safely show traceback if in IPython, else raise + ip = get_ipython() + if ip is None: + raise e + else: + ip.showtraceback() + return + try: + # exclude any figures that were closed: + active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()]) + for fig in [fig for fig in show._to_draw if fig in active]: + try: + display(fig, metadata=_fetch_figure_metadata(fig)) + except Exception as e: + # safely show traceback if in IPython, else raise + ip = get_ipython() + if ip is None: + raise e + else: + ip.showtraceback() + return + finally: + # clear flags for next round + show._to_draw = [] + show._draw_called = False + + +# Changes to matplotlib in version 1.2 requires a mpl backend to supply a default +# figurecanvas. This is set here to a Agg canvas +# See https://github.com/matplotlib/matplotlib/pull/1125 +FigureCanvas = FigureCanvasAgg + + +def configure_inline_support(shell, backend): + """Configure an IPython shell object for matplotlib use. + + Parameters + ---------- + shell : InteractiveShell instance + + backend : matplotlib backend + """ + # If using our svg payload backend, register the post-execution + # function that will pick up the results for display. This can only be + # done with access to the real shell object. + + cfg = InlineBackend.instance(parent=shell) + cfg.shell = shell + if cfg not in shell.configurables: + shell.configurables.append(cfg) + + if backend == 'module://matplotlib_inline.backend_inline': + shell.events.register('post_execute', flush_figures) + + # Save rcParams that will be overwrittern + shell._saved_rcParams = {} + for k in cfg.rc: + shell._saved_rcParams[k] = matplotlib.rcParams[k] + # load inline_rc + matplotlib.rcParams.update(cfg.rc) + new_backend_name = "inline" + else: + try: + shell.events.unregister('post_execute', flush_figures) + except ValueError: + pass + if hasattr(shell, '_saved_rcParams'): + matplotlib.rcParams.update(shell._saved_rcParams) + del shell._saved_rcParams + new_backend_name = "other" + + # only enable the formats once -> don't change the enabled formats (which the user may + # has changed) when getting another "%matplotlib inline" call. + # See https://github.com/ipython/ipykernel/issues/29 + cur_backend = getattr(configure_inline_support, "current_backend", "unset") + if new_backend_name != cur_backend: + # Setup the default figure format + select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs) + configure_inline_support.current_backend = new_backend_name + + +def _enable_matplotlib_integration(): + """Enable extra IPython matplotlib integration when we are loaded as the matplotlib backend.""" + from matplotlib import get_backend + ip = get_ipython() + backend = get_backend() + if ip and backend == 'module://%s' % __name__: + from IPython.core.pylabtools import activate_matplotlib + try: + activate_matplotlib(backend) + configure_inline_support(ip, backend) + except (ImportError, AttributeError): + # bugs may cause a circular import on Python 2 + def configure_once(*args): + activate_matplotlib(backend) + configure_inline_support(ip, backend) + ip.events.unregister('post_run_cell', configure_once) + ip.events.register('post_run_cell', configure_once) + + +_enable_matplotlib_integration() + + +def _fetch_figure_metadata(fig): + """Get some metadata to help with displaying a figure.""" + # determine if a background is needed for legibility + if _is_transparent(fig.get_facecolor()): + # the background is transparent + ticksLight = _is_light([label.get_color() + for axes in fig.axes + for axis in (axes.xaxis, axes.yaxis) + for label in axis.get_ticklabels()]) + if ticksLight.size and (ticksLight == ticksLight[0]).all(): + # there are one or more tick labels, all with the same lightness + return {'needs_background': 'dark' if ticksLight[0] else 'light'} + + return None + + +def _is_light(color): + """Determines if a color (or each of a sequence of colors) is light (as + opposed to dark). Based on ITU BT.601 luminance formula (see + https://stackoverflow.com/a/596241).""" + rgbaArr = colors.to_rgba_array(color) + return rgbaArr[:, :3].dot((.299, .587, .114)) > .5 + + +def _is_transparent(color): + """Determine transparency from alpha.""" + rgba = colors.to_rgba(color) + return rgba[3] < .5 + + +def set_matplotlib_formats(*formats, **kwargs): + """Select figure formats for the inline backend. Optionally pass quality for JPEG. + + For example, this enables PNG and JPEG output with a JPEG quality of 90%:: + + In [1]: set_matplotlib_formats('png', 'jpeg', quality=90) + + To set this in your config files use the following:: + + c.InlineBackend.figure_formats = {'png', 'jpeg'} + c.InlineBackend.print_figure_kwargs.update({'quality' : 90}) + + Parameters + ---------- + *formats : strs + One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. + **kwargs + Keyword args will be relayed to ``figure.canvas.print_figure``. + """ + # build kwargs, starting with InlineBackend config + cfg = InlineBackend.instance() + kw = {} + kw.update(cfg.print_figure_kwargs) + kw.update(**kwargs) + shell = InteractiveShell.instance() + select_figure_formats(shell, formats, **kw) + + +def set_matplotlib_close(close=True): + """Set whether the inline backend closes all figures automatically or not. + + By default, the inline backend used in the IPython Notebook will close all + matplotlib figures automatically after each cell is run. This means that + plots in different cells won't interfere. Sometimes, you may want to make + a plot in one cell and then refine it in later cells. This can be accomplished + by:: + + In [1]: set_matplotlib_close(False) + + To set this in your config files use the following:: + + c.InlineBackend.close_figures = False + + Parameters + ---------- + close : bool + Should all matplotlib figures be automatically closed after each cell is + run? + """ + cfg = InlineBackend.instance() + cfg.close_figures = close diff --git a/contrib/python/matplotlib-inline/matplotlib_inline/config.py b/contrib/python/matplotlib-inline/matplotlib_inline/config.py index c0f398069e..608015aa77 100644 --- a/contrib/python/matplotlib-inline/matplotlib_inline/config.py +++ b/contrib/python/matplotlib-inline/matplotlib_inline/config.py @@ -1,107 +1,107 @@ -"""Configurable for configuring the IPython inline backend - -This module does not import anything from matplotlib. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the BSD 3-Clause License. - -from traitlets.config.configurable import SingletonConfigurable -from traitlets import ( - Dict, Instance, Set, Bool, TraitError, Unicode -) - - -# Configurable for inline backend options -def pil_available(): - """Test if PIL/Pillow is available""" - out = False - try: - from PIL import Image # noqa - out = True - except ImportError: - pass - return out - - -# Inherit from InlineBackendConfig for deprecation purposes -class InlineBackendConfig(SingletonConfigurable): - pass - - -class InlineBackend(InlineBackendConfig): - """An object to store configuration of the inline backend.""" - - # The typical default figure size is too large for inline use, - # so we shrink the figure size to 6x4, and tweak fonts to - # make that fit. - rc = Dict( - { - 'figure.figsize': (6.0, 4.0), - # play nicely with white background in the Qt and notebook frontend - 'figure.facecolor': (1, 1, 1, 0), - 'figure.edgecolor': (1, 1, 1, 0), - # 12pt labels get cutoff on 6x4 logplots, so use 10pt. - 'font.size': 10, - # 72 dpi matches SVG/qtconsole - # this only affects PNG export, as SVG has no dpi setting - 'figure.dpi': 72, - # 10pt still needs a little more room on the xlabel: - 'figure.subplot.bottom': .125 - }, - help="""Subset of matplotlib rcParams that should be different for the - inline backend.""" - ).tag(config=True) - - figure_formats = Set( - {'png'}, - help="""A set of figure formats to enable: 'png', - 'retina', 'jpeg', 'svg', 'pdf'.""").tag(config=True) - - def _update_figure_formatters(self): - if self.shell is not None: - from IPython.core.pylabtools import select_figure_formats - select_figure_formats(self.shell, self.figure_formats, **self.print_figure_kwargs) - - def _figure_formats_changed(self, name, old, new): - if 'jpg' in new or 'jpeg' in new: - if not pil_available(): - raise TraitError("Requires PIL/Pillow for JPG figures") - self._update_figure_formatters() - - figure_format = Unicode(help="""The figure format to enable (deprecated - use `figure_formats` instead)""").tag(config=True) - - def _figure_format_changed(self, name, old, new): - if new: - self.figure_formats = {new} - - print_figure_kwargs = Dict( - {'bbox_inches': 'tight'}, - help="""Extra kwargs to be passed to fig.canvas.print_figure. - - Logical examples include: bbox_inches, quality (for jpeg figures), etc. - """ - ).tag(config=True) - _print_figure_kwargs_changed = _update_figure_formatters - - close_figures = Bool( - True, - help="""Close all figures at the end of each cell. - - When True, ensures that each cell starts with no active figures, but it - also means that one must keep track of references in order to edit or - redraw figures in subsequent cells. This mode is ideal for the notebook, - where residual plots from other cells might be surprising. - - When False, one must call figure() to create new figures. This means - that gcf() and getfigs() can reference figures created in other cells, - and the active figure can continue to be edited with pylab/pyplot - methods that reference the current active figure. This mode facilitates - iterative editing of figures, and behaves most consistently with - other matplotlib backends, but figure barriers between cells must - be explicit. - """).tag(config=True) - - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=True) +"""Configurable for configuring the IPython inline backend + +This module does not import anything from matplotlib. +""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the BSD 3-Clause License. + +from traitlets.config.configurable import SingletonConfigurable +from traitlets import ( + Dict, Instance, Set, Bool, TraitError, Unicode +) + + +# Configurable for inline backend options +def pil_available(): + """Test if PIL/Pillow is available""" + out = False + try: + from PIL import Image # noqa + out = True + except ImportError: + pass + return out + + +# Inherit from InlineBackendConfig for deprecation purposes +class InlineBackendConfig(SingletonConfigurable): + pass + + +class InlineBackend(InlineBackendConfig): + """An object to store configuration of the inline backend.""" + + # The typical default figure size is too large for inline use, + # so we shrink the figure size to 6x4, and tweak fonts to + # make that fit. + rc = Dict( + { + 'figure.figsize': (6.0, 4.0), + # play nicely with white background in the Qt and notebook frontend + 'figure.facecolor': (1, 1, 1, 0), + 'figure.edgecolor': (1, 1, 1, 0), + # 12pt labels get cutoff on 6x4 logplots, so use 10pt. + 'font.size': 10, + # 72 dpi matches SVG/qtconsole + # this only affects PNG export, as SVG has no dpi setting + 'figure.dpi': 72, + # 10pt still needs a little more room on the xlabel: + 'figure.subplot.bottom': .125 + }, + help="""Subset of matplotlib rcParams that should be different for the + inline backend.""" + ).tag(config=True) + + figure_formats = Set( + {'png'}, + help="""A set of figure formats to enable: 'png', + 'retina', 'jpeg', 'svg', 'pdf'.""").tag(config=True) + + def _update_figure_formatters(self): + if self.shell is not None: + from IPython.core.pylabtools import select_figure_formats + select_figure_formats(self.shell, self.figure_formats, **self.print_figure_kwargs) + + def _figure_formats_changed(self, name, old, new): + if 'jpg' in new or 'jpeg' in new: + if not pil_available(): + raise TraitError("Requires PIL/Pillow for JPG figures") + self._update_figure_formatters() + + figure_format = Unicode(help="""The figure format to enable (deprecated + use `figure_formats` instead)""").tag(config=True) + + def _figure_format_changed(self, name, old, new): + if new: + self.figure_formats = {new} + + print_figure_kwargs = Dict( + {'bbox_inches': 'tight'}, + help="""Extra kwargs to be passed to fig.canvas.print_figure. + + Logical examples include: bbox_inches, quality (for jpeg figures), etc. + """ + ).tag(config=True) + _print_figure_kwargs_changed = _update_figure_formatters + + close_figures = Bool( + True, + help="""Close all figures at the end of each cell. + + When True, ensures that each cell starts with no active figures, but it + also means that one must keep track of references in order to edit or + redraw figures in subsequent cells. This mode is ideal for the notebook, + where residual plots from other cells might be surprising. + + When False, one must call figure() to create new figures. This means + that gcf() and getfigs() can reference figures created in other cells, + and the active figure can continue to be edited with pylab/pyplot + methods that reference the current active figure. This mode facilitates + iterative editing of figures, and behaves most consistently with + other matplotlib backends, but figure barriers between cells must + be explicit. + """).tag(config=True) + + shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', + allow_none=True) diff --git a/contrib/python/matplotlib-inline/ya.make b/contrib/python/matplotlib-inline/ya.make index cc88039277..a48719915c 100644 --- a/contrib/python/matplotlib-inline/ya.make +++ b/contrib/python/matplotlib-inline/ya.make @@ -1,34 +1,34 @@ -# Generated by devtools/yamaker (pypi). - -PY3_LIBRARY() - -OWNER(g:python-contrib) +# Generated by devtools/yamaker (pypi). +PY3_LIBRARY() + +OWNER(g:python-contrib) + VERSION(0.1.3) -LICENSE(BSD-3-Clause) - -PEERDIR( - contrib/python/traitlets -) - -NO_LINT() - -NO_CHECK_IMPORTS( - matplotlib_inline.backend_inline -) - -PY_SRCS( - TOP_LEVEL - matplotlib_inline/__init__.py - matplotlib_inline/backend_inline.py - matplotlib_inline/config.py -) - -RESOURCE_FILES( - PREFIX contrib/python/matplotlib-inline/ - .dist-info/METADATA - .dist-info/top_level.txt -) - -END() +LICENSE(BSD-3-Clause) + +PEERDIR( + contrib/python/traitlets +) + +NO_LINT() + +NO_CHECK_IMPORTS( + matplotlib_inline.backend_inline +) + +PY_SRCS( + TOP_LEVEL + matplotlib_inline/__init__.py + matplotlib_inline/backend_inline.py + matplotlib_inline/config.py +) + +RESOURCE_FILES( + PREFIX contrib/python/matplotlib-inline/ + .dist-info/METADATA + .dist-info/top_level.txt +) + +END() |