Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for multiple display output formats in the notebook #355

Merged
merged 3 commits into from
Dec 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions holoviews/core/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand Down
17 changes: 17 additions & 0 deletions holoviews/ipython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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('<b>Warning</b>: %s' % msg))

if notebook_extension._loaded == False:
ip = get_ipython() if ip is None else ip
Expand Down
54 changes: 53 additions & 1 deletion holoviews/ipython/display_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
15 changes: 12 additions & 3 deletions holoviews/ipython/magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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.")

Expand Down Expand Up @@ -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("<b>Warning:</b> %s" % msg))

backend = Store.current_backend
return Store.renderers[backend].validate(options)

Expand Down