18

I'd like to use Matplotlib and pyplot to generate an svg image to be used in a Django framework. as of now I have it generating image files that are link to by the page, but is there a way to directly get with the svg image as a unicode string without having to write to the file system?

ciferkey
  • 2,064
  • 3
  • 20
  • 28

3 Answers3

23

Try using StringIO to avoid writing any file-like object to disk.

import matplotlib.pyplot as plt
import StringIO
from matplotlib import numpy as np

x = np.arange(0,np.pi*3,.1)
y = np.sin(x)

fig = plt.figure()
plt.plot(x,y)

imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='svg')
imgdata.seek(0)  # rewind the data

svg_dta = imgdata.buf  # this is svg data

file('test.htm', 'w').write(svg_dta)  # test it
Paul
  • 42,322
  • 15
  • 106
  • 123
  • 1
    It's probably worthwhile to point out that `cStringIO.StringIO()` provides a faster, but less flexible version of the same thing, as well. http://docs.python.org/library/stringio.html#module-cStringIO If the OP is actually going to use it in production code, it may make a difference (or not!). Regardless, a `StringIO` file-like object is definitely the way to go. – Joe Kington Mar 28 '11 at 15:22
7

Here is python3 version

import matplotlib.pyplot as plt
import numpy as np
import io

f = io.BytesIO()
a = np.random.rand(10)
plt.bar(range(len(a)), a)
plt.savefig(f, format = "svg")

print(f.getvalue()) # svg string
abasar
  • 1,659
  • 1
  • 12
  • 7
  • 1
    I could not get my browser to render the results of this, but if I replace `f = io.BytesIO()` with `f = io.StringIO()` then everything works fine – Martin CR Oct 19 '19 at 15:26
0

Based on abasar's answer, I propose the following snippet:

from io import StringIO
import matplotlib.pyplot as plt

def plot_to_svg() -> str:
    """
    Saves the last plot made using ``matplotlib.pyplot`` to a SVG string.
    
    Returns:
        The corresponding SVG string.
    """
    s = StringIO()
    plt.savefig(s, format="svg")
    plt.close()  # https://stackoverflow.com/a/18718162/14851404
    return s.getvalue()

a = [10, 20, 5]
plt.bar(range(len(a)), a)
svg = plot_to_svg()
print(svg)
mando
  • 135
  • 1
  • 8