How to create a custom HoloViews plotting backend

Taken from Philipp

import holoviews as hv
import panel as pn
import param

from holoviews.plotting.plot import GenericElementPlot, DimensionedPlot, CallbackPlot
from holoviews.plotting.renderer import Renderer

class VegaRenderer(Renderer):

    backend = param.String(default='vega', doc="The backend name.")

    
    mode_formats = {'fig': ['html', ],
                    'holomap': ['widgets', 'scrubber', 'gif', 'auto']}
    
    _render_with_panel = True

    @classmethod
    def load_nb(cls, inline=True):
        """
        Loads the plotly notebook resources.
        """
        import panel.models.vega # noqa
        cls._loaded = True
        if 'vega' not in getattr(pn.extension, '_loaded_extensions', ['vega']):
            pn.extension._loaded_extensions.append('vega')

    @classmethod
    def plot_options(cls, obj, percent_size):
        return {}

    
    def _figure_data(self, plot, fmt, as_script=False, **kwargs):
        return plot.handles['fig']


class VegaPlot(DimensionedPlot, CallbackPlot):

    backend = 'vega'

    def initialize_plot(self, ranges=None, is_geo=False):
        return self.generate_plot(self.keys[-1], ranges, is_geo=is_geo)


    def update_frame(self, key, ranges=None, is_geo=False):
        return self.generate_plot(key, ranges, is_geo=is_geo)
    
    @property
    def state(self):
        """
        The plotting state that gets updated via the update method and
        used by the renderer to generate output.
        """
        return self.handles['fig']


class CurvePlot(VegaPlot, GenericElementPlot):

    def generate_plot(self, key, ranges, element=None, is_geo=False):
        if element is None:
            element = self._get_frame(key)
        else:
            self.current_frame = element

        xdim, ydim = element.dimensions()[:2]
        
        self.handles['fig'] = fig = {
          "data": {"values": element.dframe()},
          "mark": "line",
          "encoding": {
            "x": {"field": xdim.name, "type": "quantitative"},
            "y": {"field": ydim.name, "type": "quantitative"}
          },
            "$schema": "https://vega.github.io/schema/vega-lite/v3.2.1.json"
        }
        return fig
        

pn.pane.HoloViews.param.backend.objects.append('vega')
pn.pane.HoloViews._panes['vega'] = pn.pane.Vega

hv.Store.renderers['vega'] = VegaRenderer.instance()
hv.Store.register({hv.Curve: CurvePlot}, backend='vega')

# Needs a fix in hv.util.__init__.py
# hv.extension._backends['vega'] = 'vega'

hv.extension('vega')
hv.Store.current_backend = 'vega'

# Need another fix in the HoloViews pane

hv.Curve([1, 2, 3])
1 Like