Saving Interactive Matplotlib Figures

Saving interactive Matplotlib figures

This would be a great feature, but AFAIK it isn't implemented in Matplotlib and likely would be difficult to implement yourself due to the way figures are stored.

I'd suggest either (a) separate processing the data from generating the figure (which saves data with a unique name) and write a figure generating script (loading a specified file of the saved data) and editing as you see fit or (b) save as PDF/SVG/PostScript format and edit in some fancy figure editor like Adobe Illustrator (or Inkscape).

EDIT post Fall 2012: As others pointed out below (though mentioning here as this is the accepted answer), Matplotlib since version 1.2 allowed you to pickle figures. As the release notes state, it is an experimental feature and does not support saving a figure in one matplotlib version and opening in another. It's also generally unsecure to restore a pickle from an untrusted source.

For sharing/later editing plots (that require significant data processing first and may need to be tweaked months later say during peer review for a scientific publication), I still recommend the workflow of (1) have a data processing script that before generating a plot saves the processed data (that goes into your plot) into a file, and (2) have a separate plot generation script (that you adjust as necessary) to recreate the plot. This way for each plot you can quickly run a script and re-generate it (and quickly copy over your plot settings with new data). That said, pickling a figure could be convenient for short term/interactive/exploratory data analysis.

Saving interactive series on matplotlib figures (html)

It is not possible to maintain the matplotlib.widget interactivity in an html file generated by mpld3. This is because the javascript generated by mpld3 runs client-side and cannot access the Python kernel that generated it.

You can achieve something like the matplotlib interactivity in an html version using the Static Interactive Widgets for IPython Notebooks approach.

Save 3D Matplot as interactive HTML

As far as I'm aware, Matplotlib is not able to generate 3D html plot.

Moreover, what you tried above is wrong. That error message is telling you that Plotly's to_html only works with Plotly's Figure. So mixing Plotly and Matplotlib is not going to work. You need to create a Plotly figure.

Also, I don't think that Plotly exposes something similar to Matplotlib's plot_trisurf. However, it exposes go.Mesh that allows us to achieve the same result.

The recipe:

  • Generate your numerical data.
  • Create a triangulation. We will use Matplotlib's Triangulation class for this part.
  • Create the Plotly figure and add the surface.
  • Export the figure to html.

Here I'm going to post an example to guide you:

import numpy as np
import matplotlib.tri as mtri
import plotly.graph_objects as go

### DATA GENERATION
# Make parameter spaces radii and angles.
n_angles = 36
n_radii = 8
min_radius = 0.25
radii = np.linspace(min_radius, 0.95, n_radii)

angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
angles[:, 1::2] += np.pi/n_angles

# Map radius, angle pairs to x, y, z points.
x = (radii*np.cos(angles)).flatten()
y = (radii*np.sin(angles)).flatten()
z = (np.cos(radii)*np.cos(3*angles)).flatten()

### TRIANGULATION
# Create the Triangulation; no triangles so Delaunay triangulation created.
triang = mtri.Triangulation(x, y)

# Mask off unwanted triangles.
xmid = x[triang.triangles].mean(axis=1)
ymid = y[triang.triangles].mean(axis=1)
mask = xmid**2 + ymid**2 < min_radius**2
triangles = triang.triangles[~mask]

### PLOT
fig = go.Figure(data=[
# go.Mesh allows to provide the triangulation
go.Mesh3d(
x=x, y=y, z=z,
colorbar_title='z',
colorscale="aggrnyl",
# Intensity of each vertex, which will be interpolated and color-coded
intensity =z,
# i, j and k give the vertices of triangles
i = triangles[:, 0],
j = triangles[:, 1],
k = triangles[:, 2],
showscale=True
)
])

fig.show()

### EXPORT TO HTML
# Please, execute `help(fig.write_html)` to learn about all the
# available keyword arguments to control the output
fig.write_html("test.html", include_plotlyjs=True, full_html=True)

Dynamically serving a matplotlib image to the web using python

You should

  • first write to a cStringIO object
  • then write the HTTP header
  • then write the content of the cStringIO to stdout

Thus, if an error in savefig occured, you could still return something else, even another header. Some errors won't be recognized earlier, e.g., some problems with texts, too large image dimensions etc.

You need to tell savefig where to write the output. You can do:

format = "png"
sio = cStringIO.StringIO()
pyplot.savefig(sio, format=format)
print "Content-Type: image/%s\n" % format
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) # Needed this on windows, IIS
sys.stdout.write(sio.getvalue())

If you want to embed the image into HTML:

print "Content-Type: text/html\n"
print """<html><body>
...a bunch of text and html here...
<img src="data:image/png;base64,%s"/>
...more text and html...
</body></html>""" % sio.getvalue().encode("base64").strip()

how to edit the saved graph by matplotlib?

As said by Arjun Muraleedharan, once you save your plot in Matplotlib, you will not be able to modify it.

However, if your problem is with the axes overlapping in the image, then try plt.tight_layout(). Call this just before your plt.show() in your code, assuming you did import matplotlib.pyplot as plt.

What it does is it prevents any overlapping of anything in your plots and makes everything look a lot neater, which (I think) is what you are looking for.



Related Topics



Leave a reply



Submit