Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include output from %matplotlib notebook backend as SVG in ipynb

This answer from a few years ago shows how you can make jupyter notebook create graphs as svg. The solution is to tell the InlineBackend to use svg as output.

import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
plt.plot(...)

This will cause all images to be in svg format inside the notebook as well as in the produced ipynb file; the file will have a line like

"data": {  "image/svg+xml": [  "<?xml  .....

in it.

The problem is now that this does not work if the %matplotlib notebook backend is used. %config InlineBackend does not change anything for the notebook backend, hence the output file contains a PNG image

"data": { "text/html": [  "<img src=\"data:image/png;base64,iVBORw0....

So the question is: How do I get the ipynb file to include a static version of the plot that is created with the %matplotlib notebook backend as SVG image?

There is a small comment by @mark jay from one month ago, who wanted to do exactly what I would like to do now, but there is no answer or hint to that comment.

In my code I have plotted directly from the dataframe:

%matplotlib notebook
import pandas as pd
df = pd.read_sql(sql1, connection)
...
...
df.plot(subplots=True, kind='bar')

This functions perfectly well without importing matplotlib.pyplot but it also can't be coerced to create the graphic as an svg. I suppose if the base case would work, I could modify the plotting code so it did not involve pandas or dataframes.

like image 554
cardamom Avatar asked Aug 02 '17 17:08

cardamom


People also ask

How do you use %Matplotlib in Jupyter?

Install Matplotlib Make sure you first have Jupyter notebook installed, then we can add Matplotlib to our virtual environment. To do so, navigate to the command prompt and type pip install matplotlib. Now launch your Jupyter notebook by simply typing jupyter notebook at the command prompt.

What does %Matplotlib do in Jupyter?

In the IPython notebook, you also have the option of embedding graphics directly in the notebook, with two possible options: %matplotlib notebook will lead to interactive plots embedded within the notebook. %matplotlib inline will lead to static images of your plot embedded in the notebook.

What happens if I dont use %Matplotlib inline?

It just means that any graph which we are creating as a part of our code will appear in the same notebook and not in separate window which would happen if we have not used this magic statement.


2 Answers

Since apparently even after a bounty period noone was able to provide a solution, a workaround may be the following.

  1. Create you notebook with %matplotlib notebook. Once you're satisfied with the result, save it.
  2. Use a copy of it and replace %matplotlib notebook with

    %matplotlib inline
    %config InlineBackend.figure_format = 'svg'
    

    Rerun the complete notebook. Save the result.

  3. Open the resulting ipynb file in a text editor and replace the previous two lines again with %matplotlib notebook.

The final result will be a ipynb with svg images. But once opened and run, it will use the notebook backend for figure creation.

like image 148
ImportanceOfBeingErnest Avatar answered Oct 26 '22 23:10

ImportanceOfBeingErnest


From whatI understand from reading about matplotlib backends, nbagg, which is called using %matplotlib notebook uses the Agg (Anti-Grain Geometry) render which is not capable of rendering vector graphics. Unfortunately this is the only out of the box way of using an interactive inline backend for Jupyter.

Docs Link https://matplotlib.org/faq/usage_faq.html#what-is-interactive-mode
Similar Answer How to make matplotlibs nbagg backend generate SVGs?

If you don't need the interactivity just keep use

import pandas as pd
from IPython.display import SVG, display
from numpy import ndarray

def svg_add(chart, size=(4,4), dpi=100):
    """Takes a chart, optional tuple of ints for size, int for dpi
    default is 4 by 4 inches with 100 dpi"""

    if type(chart) == ndarray:
        fig = chart[0].get_figure()
        fig.set_size_inches(size)
        fig.savefig("mybar.svg", dpi=dpi)
        display(SVG(filename='mybar.svg'))
    else:
        fig = chart.get_figure()
        fig.set_size_inches(size)
        fig.savefig("mybar.svg", dpi=dpi)
        display(SVG(filename='mybar.svg'))

then

df = pd.DataFrame([[2,5]],columns=['a','b'])
bar_chart = df.plot(subplots=False, kind='bar')
svg_add(chart=bar_chart,size=(3,3),dpi=100)
#or
#svg_add(bar_chart,(3,3),100)
like image 21
fcsr Avatar answered Oct 26 '22 23:10

fcsr