5

I would like to save a holoviews plot as a SVG, however I am getting an error message that I don't understand:

    np.random.seed(9)
    data = np.random.rand(10, 2)
    points = hv.Points(data)
    labels = hv.Labels({('x', 'y'): data, 'text': [chr(65+i) for i in range(10)]}, ['x', 'y'], 'text')
    overlay = (points * labels).redim.range(x=(-0.2, 1.2), y=(-.2, 1.2))
    
    overlay.opts(
        opts.Labels(text_font_size='10pt', xoffset=0.08),
        opts.Points(color='black', size=5))
    
    hv.save(overlay, 'overlay.svg', fmt='svg')
    ---------------------------------------------------------------------------
    Exception                                 Traceback (most recent call last)
    <ipython-input-29-b23ca97e9c01> in <module>
          9     opts.Points(color='black', size=5))
         10 
    ---> 11 hv.save(overlay, 'overlay.svg', fmt='svg')
    
    ~/miniconda3/envs/mybrew/lib/python3.7/site-packages/holoviews/util/__init__.py in save(obj, filename, fmt, backend, resources, toolbar, title, **kwargs)
        818             filename = '.'.join(formats[:-1])
        819     return renderer_obj.save(obj, filename, fmt=fmt, resources=resources,
    --> 820                              title=title)
        821 
        822 
    
    ~/miniconda3/envs/mybrew/lib/python3.7/site-packages/holoviews/plotting/renderer.py in save(self_or_cls, obj, basename, fmt, key, info, options, resources, title, **kwargs)
        592 
        593         with StoreOptions.options(obj, options, **kwargs):
    --> 594             plot, fmt = self_or_cls._validate(obj, fmt)
        595 
        596         if isinstance(plot, Viewable):
    
    ~/miniconda3/envs/mybrew/lib/python3.7/site-packages/holoviews/plotting/renderer.py in _validate(self, obj, fmt, **kwargs)
        302         if fmt not in all_formats:
        303             raise Exception("Format %r not supported by mode %r. Allowed formats: %r"
    --> 304                             % (fmt, self.mode, fig_formats + holomap_formats))
        305         self.last_plot = plot
        306         return plot, fmt
    
    Exception: Format 'svg' not supported by mode 'default'. Allowed formats: ['html', 'auto', 'png', 'widgets', 'scrubber', 'gif', 'auto', None]

Would anyone have a clue why this might be happening? According to the docs:

http://holoviews.org/user_guide/Exporting_and_Archiving.html

export to SVG should be possible.

Steve OB
  • 63
  • 6

1 Answers1

5

The problem occurs when using the default 'bokeh' backend. I found a solution here:

import holoviews as hv
from bokeh.io import export_svgs

def export_svg(obj, filename):
    plot_state = hv.renderer('bokeh').get_plot(obj).state
    plot_state.output_backend = 'svg'
    export_svgs(plot_state, filename=filename)

overlay = hv.Overlay(...)
export_svg(overlay, 'overlay.svg')

However, for some reason point elements are not rendered with this method.

Another solution is to switch to the 'matplotlib' backend (the first line in the code below), then hv.save(...) works. Unfortunately the two backends are not compatible with all options. For example, in your case, you have to change text_font_size to fontsize and size to s and raise the value to two for corresponding scaling:

hv.extension('matplotlib')

np.random.seed(9)
data = np.random.rand(10, 2)
points = hv.Points(data)
labels = hv.Labels({('x', 'y'): data, 'text': [chr(65+i) for i in range(10)]}, ['x', 'y'], 'text')
overlay = (points * labels).redim.range(x=(-0.2, 1.2), y=(-.2, 1.2))

overlay.opts(
    hv.opts.Labels(fontsize=10, xoffset=0.08),
    hv.opts.Points(color='black', s=25))

hv.save(overlay, 'overlay.svg', fmt='svg')
overlay

It would certainly help if Holoviews had a unified api to the style options just as it does for the visual elements.

  • 1
    Would be nice if a [Layout](http://holoviews.org/reference/containers/matplotlib/Layout.html) (collection of HoloViews objects) could also be exported to svg. I think currently this is impossible. – mouwsy Jan 25 '21 at 11:08
  • Well, if I use the code for MatPlotLib I get 'Figure' object has no attribute 'traverse' – Dario de Judicibus Jan 15 '22 at 10:18