From 351b13d85d8728069fcee2b46b6b90d05f68e7f9 Mon Sep 17 00:00:00 2001 From: jlstevens Date: Sun, 13 Dec 2015 01:46:48 +0000 Subject: [PATCH 1/3] Added display_formats to Store and notebook_extension --- holoviews/core/options.py | 4 ++++ holoviews/ipython/__init__.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/holoviews/core/options.py b/holoviews/core/options.py index ab2a3aaac0..f5185f6d11 100644 --- a/holoviews/core/options.py +++ b/holoviews/core/options.py @@ -769,6 +769,10 @@ class Store(object): # types grouped by the backend. Set using the register method. registry = {} + # A list of formats to be published for display on the frontend (e.g + # IPython Notebook or a GUI application) + display_formats = ['html'] + # Once register_plotting_classes is called, this OptionTree is # populated for the given backend. _options = {} diff --git a/holoviews/ipython/__init__.py b/holoviews/ipython/__init__.py index 3e37c80eec..371d0b3b7c 100644 --- a/holoviews/ipython/__init__.py +++ b/holoviews/ipython/__init__.py @@ -105,6 +105,16 @@ class notebook_extension(param.ParameterizedFunction): width = param.Number(default=None, bounds=(0, 100), doc=""" Width of the notebook as a percentage of the browser screen window width.""") + display_formats = param.List(default=['html'], doc=""" + A list of formats that are rendered to the notebook where + multiple formats may be selected at once (although only one + format will be displayed). + + Although the 'html' format is supported across backends, other + formats supported by the current backend (e.g 'png' and 'svg' + using the matplotlib backend) may be used. This may be useful to + export figures to other formats such as PDF with nbconvert. """) + ip = param.Parameter(default=None, doc="IPython kernel instance") _loaded = False @@ -113,6 +123,13 @@ def __call__(self, **params): resources = self._get_resources(params) ip = params.pop('ip', None) p = param.ParamOverrides(self, params) + Store.display_formats = p.display_formats + + if 'html' not in p.display_formats and len(p.display_formats) > 1: + msg = ('Output magic unable to control displayed format ' + 'as IPython notebook uses fixed precedence ' + 'between %r' % p.display_formats) + display(HTML('Warning: %s' % msg)) if notebook_extension._loaded == False: ip = get_ipython() if ip is None else ip From 9e2ec3b1006f4d1b9f4b146933cc2201e8fab701 Mon Sep 17 00:00:00 2001 From: jlstevens Date: Sun, 13 Dec 2015 01:48:41 +0000 Subject: [PATCH 2/3] Added optional PNG and SVG display hooks --- holoviews/ipython/display_hooks.py | 54 +++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/holoviews/ipython/display_hooks.py b/holoviews/ipython/display_hooks.py index 0d84e8d639..bf4ae1e56b 100644 --- a/holoviews/ipython/display_hooks.py +++ b/holoviews/ipython/display_hooks.py @@ -188,13 +188,59 @@ def display(obj, raw=False, **kwargs): def pprint_display(obj): - # If pretty printing is off, return None (will fallback to repr) + if 'html' not in Store.display_formats: + return None + + # If pretty printing is off, return None (fallback to next display format) ip = get_ipython() # # pyflakes:ignore (in IPython namespace) if not ip.display_formatter.formatters['text/plain'].pprint: return None return display(obj, raw=True) +@display_hook +def element_png_display(element, max_frames, max_branches): + """ + Used to render elements to PNG if requested in the display formats. + """ + if 'png' not in Store.display_formats: + return None + info = process_object(element) + if info: return info + + backend = Store.current_backend + if type(element) not in Store.registry[backend]: + return None + renderer = Store.renderers[backend] + # Current renderer does not support PNG + if 'png' not in renderer.params('fig').objects: + return None + + data, info = renderer(element, fmt='png') + return data + + +@display_hook +def element_svg_display(element, max_frames, max_branches): + """ + Used to render elements to SVG if requested in the display formats. + """ + if 'svg' not in Store.display_formats: + return None + info = process_object(element) + if info: return info + + backend = Store.current_backend + if type(element) not in Store.registry[backend]: + return None + renderer = Store.renderers[backend] + # Current renderer does not support SVG + if 'svg' not in renderer.params('fig').objects: + return None + data, info = renderer(element, fmt='svg') + return data + + # display_video output by default, but may be set to first_frame, # middle_frame or last_frame (e.g. for testing purposes) render_anim = None @@ -205,3 +251,9 @@ def set_display_hooks(ip): html_formatter.for_type(UniformNdMapping, pprint_display) html_formatter.for_type(AdjointLayout, pprint_display) html_formatter.for_type(Layout, pprint_display) + + png_formatter = ip.display_formatter.formatters['image/png'] + png_formatter.for_type(ViewableElement, element_png_display) + + svg_formatter = ip.display_formatter.formatters['image/svg+xml'] + svg_formatter.for_type(ViewableElement, element_svg_display) From f39cf843e2209fc6b9715f55eae2e818ebd25e8f Mon Sep 17 00:00:00 2001 From: jlstevens Date: Sun, 13 Dec 2015 01:49:29 +0000 Subject: [PATCH 3/3] Output magic now validates fig against Store.display_formats --- holoviews/ipython/magics.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index 7b734202be..5da3d94149 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -60,6 +60,7 @@ def update_options(cls, options, items): Allows updating options depending on class attributes and unvalidated options. """ + pass @classmethod def get_options(cls, line, options, linemagic): @@ -98,10 +99,10 @@ def get_options(cls, line, options, linemagic): raise ValueError("Value %r for key %r not between %s and %s" % info) options[keyword] = value - return cls._validate(options, linemagic) + return cls._validate(options, items, linemagic) @classmethod - def _validate(cls, options, linemagic): + def _validate(cls, options, items, linemagic): "Allows subclasses to check options are valid." raise NotImplementedError("OptionsMagic is an abstract base class.") @@ -303,8 +304,16 @@ def _generate_docstring(cls): @classmethod - def _validate(cls, options, linemagic): + def _validate(cls, options, items, linemagic): "Validation of edge cases and incompatible options" + + if 'html' in Store.display_formats: + pass + elif 'fig' in items and items['fig'] not in Store.display_formats: + msg = ("Output magic requesting figure format %r " % items['fig'] + + "not in display formats %r" % Store.display_formats) + display(HTML("Warning: %s" % msg)) + backend = Store.current_backend return Store.renderers[backend].validate(options)