How to wrap an existing Boheh plot into HoloViews?

Hi all,

Is it possible to wrap an existing plot into HoloViews so that it can interact with other elements as usual? It will be handy when a corresponding Element type is unavailable.

For example, how to make the following plot available in HoloViews? Thanks

from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.sampledata.sprint import sprint

output_file("bar_intervals.html")

sprint.Year = sprint.Year.astype(str)
group = sprint.groupby('Year')
source = ColumnDataSource(group)

p = figure(y_range=group, x_range=(9.5,12.7), plot_width=400, plot_height=550, toolbar_location=None,
           title="Time Spreads for Sprint Medalists (by Year)")
p.hbar(y="Year", left='Time_min', right='Time_max', height=0.4, source=source)

p.ygrid.grid_line_color = None
p.xaxis.axis_label = "Time (seconds)"
p.outline_line_color = None

show(p)

So this is a bit of hack and doesn’t support some of the features usually supported by other elements but it at least makes it possible to embed a static bokeh figure in a HoloViews layout. It does not support overlaying (with *) or updating in a DynamicMap and/or HoloMap:

from holoviews.core import Element
from holoviews.plotting.bokeh import ElementPlot

class BokehPlot(Element):
   """
   Allows embedding a bokeh figure in a HoloViews layout.
   """

class BokehFigurePlot(ElementPlot):
    
    def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
        plot = self.hmap.last.data
        self.handles['plot'] = plot
        return plot

hv.Store.register({BokehPlot: BokehFigurePlot}, 'bokeh')

BokehPlot(p) + hv.Curve([1, 2, 3])

If you just need to lay out a plot like this it probably ends up being cleaner to just use Panel to compose the HoloViews and Bokeh plots.

A belated but big thank you. Indeed I used Panel to compose the plots. Thank you again.

2 Likes

Even I you have deleted your message, here is a quick example of streaming candlestick:

import yfinance as yf
import holoviews as hv
hv.extension('bokeh')

msft = yf.Ticker("MSFT")
df = msft.history(period="1y", interval='1d').reset_index()
t_delta = np.median(np.diff(df.Date))
df['Start'] = df.Date - t_delta/4 # rectangles start
df['End'] = df.Date + t_delta/4 # rectangles end
df['Positive'] = ((df.Close - df.Open)>0).astype(int)

def make_candle_stick(data):
    candlestick = hv.Segments(data, kdims=['Date', 'Low', 'Date', 'High']) * hv.Rectangles(data, kdims=['Start','Open', 'End', 'Close'], vdims=['Positive'])
    candlestick = candlestick.redim.label(Low='Values')
    return candlestick.opts(hv.opts.Rectangles(color='Positive', cmap=['red', 'green'], colorbar=True), hv.opts.Segments(color='black'))
dfstream = hv.streams.Buffer(data=df.iloc[:2], length=30, index=False)
hv.DynamicMap(make_candle_stick, streams=[dfstream]).opts(responsive=True, height=400, show_grid=True)

And to stream data:

import time
def make_data():
    count = 2
    while True:
        count += 1
        yield df.iloc[count-1:count]
data = make_data()
for i in range(len(df)-2):
    time.sleep(0.1)
    dfstream.send(next(data))

4 Likes