From fa723eb4f73a4c43b801bc1abcffa7e3ba5944d6 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 16 Mar 2017 21:15:25 +0000 Subject: [PATCH 1/6] Added support for plotting matplotlib from commandline --- holoviews/plotting/bokeh/renderer.py | 2 ++ holoviews/plotting/mpl/__init__.py | 9 --------- holoviews/plotting/mpl/plot.py | 5 +++++ holoviews/plotting/mpl/renderer.py | 30 +++++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index 7f0b97529b..9c5434158c 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -190,4 +190,6 @@ def load_nb(cls, inline=True): """ Loads the bokeh notebook resources. """ + import matplotlib.pyplot as plt + plt.switch_backend('agg') load_notebook(hide_banner=True, resources=INLINE if inline else CDN) diff --git a/holoviews/plotting/mpl/__init__.py b/holoviews/plotting/mpl/__init__.py index 12974b462c..ece855f26f 100644 --- a/holoviews/plotting/mpl/__init__.py +++ b/holoviews/plotting/mpl/__init__.py @@ -1,12 +1,3 @@ - -try: - # Switching to 'agg' backend (may be overridden in holoviews.rc) - import matplotlib.pyplot as plt - plt.switch_backend('agg') -except: - pass - - import os from distutils.version import LooseVersion diff --git a/holoviews/plotting/mpl/plot.py b/holoviews/plotting/mpl/plot.py index 10199034d4..9003b31007 100644 --- a/holoviews/plotting/mpl/plot.py +++ b/holoviews/plotting/mpl/plot.py @@ -130,6 +130,11 @@ def __init__(self, fig=None, axis=None, **params): 'finalize_hooks, not both.') self.finalize_hooks = self.final_hooks self.handles['bbox_extra_artists'] = [] + if self.renderer.interactive: + plt.ion() + self._close_figures = False + else: + plt.ioff() def _init_axis(self, fig, axis): diff --git a/holoviews/plotting/mpl/renderer.py b/holoviews/plotting/mpl/renderer.py index 424b993eed..78c2014a06 100644 --- a/holoviews/plotting/mpl/renderer.py +++ b/holoviews/plotting/mpl/renderer.py @@ -53,12 +53,15 @@ class MPLRenderer(Renderer): Output render multi-frame (typically animated) format. If None, no multi-frame rendering will occur.""") + interactive = param.Boolean(default=False, doc=""" + Whether to enable interactive plotting allowing interactive + plotting with explicitly calling show.""") + mode = param.ObjectSelector(default='default', objects=['default', 'mpld3', 'nbagg'], doc=""" The 'mpld3' mode uses the mpld3 library whereas the 'nbagg' uses matplotlib's the experimental nbagg backend. """) - # : (animation writer, format, anim_kwargs, extra_args) ANIMATION_OPTS = { 'webm': ('ffmpeg', 'webm', {}, @@ -112,6 +115,23 @@ def __call__(self, obj, fmt='auto'): 'mime_type':MIME_TYPES[fmt]} + def show(self, obj): + """ + Renders the supplied object and displays it using the active + GUI backend. + """ + from .plot import MPLPlot + MPLPlot._close_figures = False + try: + plot = self.get_plot(obj) + plot.initialize_plot() + plt.show(plot.state) + except: + MPLPlot._close_figures = True + raise + MPLPlot._close_figures = True + + @classmethod def plot_options(cls, obj, percent_size): """ @@ -279,3 +299,11 @@ def validate(cls, options): "matplotlib:nbagg.\nSwitching widget mode to 'live'.") options['widgets'] = 'live' return options + + @classmethod + def load_nb(cls, inline=True): + """ + Initialize matplotlib backend + """ + import matplotlib.pyplot as plt + plt.switch_backend('agg') From e497429e7e3ffc06304dd124d71257827405c2a1 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 16 Mar 2017 22:01:58 +0000 Subject: [PATCH 2/6] Implemented initial BokehRenderer.show --- holoviews/plotting/bokeh/renderer.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index 9c5434158c..f6e20ed835 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -1,4 +1,6 @@ import uuid +import time +import tempfile import numpy as np import param @@ -6,12 +8,13 @@ from bokeh.charts import Chart from bokeh.document import Document -from bokeh.embed import notebook_div +from bokeh.embed import notebook_div, file_html from bokeh.io import load_notebook, curdoc from bokeh.models import (Row, Column, Plot, Model, ToolbarBox, WidgetBox, Div, DataTable, Tabs) from bokeh.plotting import Figure from bokeh.resources import CDN, INLINE +from bokeh.util.browser import view as browser_view from ...core import Store, HoloMap from ..comms import JupyterComm, Comm @@ -117,6 +120,19 @@ def figure_data(self, plot, fmt='html', doc=None, **kwargs): plot.document = doc return div + def show(self, obj, browser=None, resource=CDN): + """ + Renders the supplied object and displays it using specified browser. + """ + plot = self.get_plot(obj) + plot.initialize_plot() + html = file_html(plot.state, resource) + tf = tempfile.NamedTemporaryFile('w') + tf.write(html) + tf.seek(0) + browser_view(tf.name, browser) + time.sleep(5) + tf.close() def diff(self, plot, serialize=True): """ From 752efc263b0d9a2b7ff578fbd7289f3f3b29f498 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 17 Mar 2017 20:08:40 +0000 Subject: [PATCH 3/6] Small fix to interactive plotting with MPLRenderer --- holoviews/plotting/mpl/renderer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/holoviews/plotting/mpl/renderer.py b/holoviews/plotting/mpl/renderer.py index 78c2014a06..5589006a0d 100644 --- a/holoviews/plotting/mpl/renderer.py +++ b/holoviews/plotting/mpl/renderer.py @@ -120,16 +120,19 @@ def show(self, obj): Renders the supplied object and displays it using the active GUI backend. """ + if self.interactive: + return self.get_plot(obj) + from .plot import MPLPlot MPLPlot._close_figures = False try: plot = self.get_plot(obj) - plot.initialize_plot() plt.show(plot.state) except: MPLPlot._close_figures = True raise MPLPlot._close_figures = True + return plot @classmethod From 86bee49a1876c438403ec7d06900a7ca324d7963 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 17 Mar 2017 20:18:13 +0000 Subject: [PATCH 4/6] Enable interactive plotting before creating first figure --- holoviews/plotting/mpl/plot.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/holoviews/plotting/mpl/plot.py b/holoviews/plotting/mpl/plot.py index 9003b31007..97554273b7 100644 --- a/holoviews/plotting/mpl/plot.py +++ b/holoviews/plotting/mpl/plot.py @@ -119,6 +119,12 @@ def __init__(self, fig=None, axis=None, **params): if self.fig_latex: self.fig_rcparams['text.usetex'] = True + if self.renderer.interactive: + plt.ion() + self._close_figures = False + else: + plt.ioff() + with mpl.rc_context(rc=self.fig_rcparams): fig, axis = self._init_axis(fig, axis) @@ -130,11 +136,6 @@ def __init__(self, fig=None, axis=None, **params): 'finalize_hooks, not both.') self.finalize_hooks = self.final_hooks self.handles['bbox_extra_artists'] = [] - if self.renderer.interactive: - plt.ion() - self._close_figures = False - else: - plt.ioff() def _init_axis(self, fig, axis): From 986cdf32e5f1ca15c45f3caddbf0dbadd9f618ed Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Sat, 18 Mar 2017 00:52:35 +0000 Subject: [PATCH 5/6] MPLRenderer.show allows passing in multiple objects --- holoviews/plotting/mpl/renderer.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/holoviews/plotting/mpl/renderer.py b/holoviews/plotting/mpl/renderer.py index 5589006a0d..e9f80cd1a8 100644 --- a/holoviews/plotting/mpl/renderer.py +++ b/holoviews/plotting/mpl/renderer.py @@ -121,18 +121,23 @@ def show(self, obj): GUI backend. """ if self.interactive: + if isinstance(obj, list): + return [self.get_plot(o) for o in obj] return self.get_plot(obj) from .plot import MPLPlot MPLPlot._close_figures = False try: - plot = self.get_plot(obj) - plt.show(plot.state) + plots = [] + objects = obj if isinstance(obj, list) else [obj] + for o in obj: + plots.append(self.get_plot(o)) + plt.show() except: MPLPlot._close_figures = True raise MPLPlot._close_figures = True - return plot + return plots[0] if len(plots) == 1 else plots @classmethod From 2d4235988a93e5990786c405a21393d40ab7d629 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Sat, 8 Apr 2017 20:43:31 +0100 Subject: [PATCH 6/6] Reverted adding BokehRenderer.show --- holoviews/plotting/bokeh/renderer.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py index f6e20ed835..7f0b97529b 100644 --- a/holoviews/plotting/bokeh/renderer.py +++ b/holoviews/plotting/bokeh/renderer.py @@ -1,6 +1,4 @@ import uuid -import time -import tempfile import numpy as np import param @@ -8,13 +6,12 @@ from bokeh.charts import Chart from bokeh.document import Document -from bokeh.embed import notebook_div, file_html +from bokeh.embed import notebook_div from bokeh.io import load_notebook, curdoc from bokeh.models import (Row, Column, Plot, Model, ToolbarBox, WidgetBox, Div, DataTable, Tabs) from bokeh.plotting import Figure from bokeh.resources import CDN, INLINE -from bokeh.util.browser import view as browser_view from ...core import Store, HoloMap from ..comms import JupyterComm, Comm @@ -120,19 +117,6 @@ def figure_data(self, plot, fmt='html', doc=None, **kwargs): plot.document = doc return div - def show(self, obj, browser=None, resource=CDN): - """ - Renders the supplied object and displays it using specified browser. - """ - plot = self.get_plot(obj) - plot.initialize_plot() - html = file_html(plot.state, resource) - tf = tempfile.NamedTemporaryFile('w') - tf.write(html) - tf.seek(0) - browser_view(tf.name, browser) - time.sleep(5) - tf.close() def diff(self, plot, serialize=True): """ @@ -206,6 +190,4 @@ def load_nb(cls, inline=True): """ Loads the bokeh notebook resources. """ - import matplotlib.pyplot as plt - plt.switch_backend('agg') load_notebook(hide_banner=True, resources=INLINE if inline else CDN)