How to use hvplot and/or holoviews without jupyter & with matplotlib (from a pure Python script)

Hello all,

I’m new to the HoloViz ecosystem, and I’m very excited I found it. The documentation is pretty good, but 1 thing I couldn’t find and is stopping me from using it altogether, and that is: How to make hvplot use an existing figure and axis I create with Matplotlib? Is this supported? As the title says, I’m not using Jupyter at all (and I don’t want to), and I’m using a pure Python script to read my data and plot it.

The only full examples I could find on holoviews’ docs were generating SVG images, and not creating a figure that you can plt.show()

Hi @doronbehar

Welcome to the community.

I don’t know how you can use an existing Matplotlib Figure.

Some strategies for showing the Matplotlib figure is

  • To save the figure (as you described) does not work for you.
  • Use Figure.show() which is really only useful in Notebook or ipython terminal
  • Use Panel to serve or show the figure

Figure.show()

import hvplot.pandas
import pandas as pd
from matplotlib.figure import Figure
import holoviews as hv
import panel as pn

df = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': [10, 20, 30, 40]
})

plot = df.hvplot('x', 'y')

fig = hv.render(plot, backend='matplotlib')
fig.show()

Please not that Python will continue past the fig.show() line and finish the script unless you are in ipython console or notebook.

Panel .servable()

import hvplot.pandas
import pandas as pd
from matplotlib.figure import Figure
import holoviews as hv
import panel as pn

pn.extension()

df = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': [10, 20, 30, 40]
})

plot = df.hvplot('x', 'y')

fig = hv.render(plot, backend='matplotlib')

pn.pane.Matplotlib(fig, height=500, width=500).servable()
panel serve script.py --dev

Personally I would use the script below because its shorter.

import hvplot.pandas
import pandas as pd
from matplotlib.figure import Figure
import holoviews as hv
import panel as pn

pn.extension()

df = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': [10, 20, 30, 40]
})

plot = df.hvplot('x', 'y')

pn.pane.HoloViews(plot, height=500, width=500, backend="matplotlib").servable()

Panel .show()

import hvplot.pandas
import pandas as pd
from matplotlib.figure import Figure
import holoviews as hv
import panel as pn

pn.extension()

df = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': [10, 20, 30, 40]
})

plot = df.hvplot('x', 'y')

fig = hv.render(plot, backend='matplotlib')

pn.pane.Matplotlib(fig, height=500, width=500).show()
python script.py

Wondering why you need to use an existing figure? It could be possible through hooks Customizing Plots — HoloViews v1.19.1

I think a better approach would be starting with hvplot/holoviews → hook/backend_opts to matplotlib figure and do further customizations

Thank you for all your replies!

Indeed I don’t have to use an existing Matplotlib figure, I won’t mind using a subfigure if that is possible, or add subplots to the figure that hvplot will create, and do there whatever I want, if that is possible.

I’ll summarize the results from testing your suggestions:

Indeed that is correct. But as I said before, I don’t use Jupyter or Ipython, so this doesn’t actually show the figure, and hence it is not working for me :(. Please tell me if I missed something, as it feels very close to what I wish to do.

That works (with running panel serve), but I would really like to not use the web, and use the native Matplotlib

Works too, but still, I want to use the native Matplotlib interface, and not the web interface.

That sounds pretty good, but it is still not clear to me how to make the figures there actually show up, that’s what is so frustrating me.

I couldn’t find a way to do it:

import matplotlib.pyplot as plt
import holoviews as hv
import matplotlib

hv.extension("matplotlib")
matplotlib.use("nbAgg")



c = hv.Curve([0, 1, 2])


fig = hv.renderer("matplotlib").get_plot(c).state
plt.switch_backend("tkagg") # I think this closes all figures
print(fig)
plt.show(block=False)

What’s the remaining issue? Seems like the renderer should give you a matplotlib figure and you can then do with it what you like?

The request is:

native Matplotlib interface, and not the web interface.

the native tkinter(?) UI doesn’t show because somewhere, Holoviews uses agg which is a non-interactive backend, and when we switch back the agg, all the figures get closed. However, it’s possible to save the figure and re-open it, or use panel to display it

1 Like