Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib: How to create original backend

The following program does not work on non-GUI environments. I want to let this program save the figure to a temporary png file when plt.show is called.

import matplotlib.pyplot as plt
plt.scatter(2,3)
plt.scatter(4,5)
plt.show()

I know that this can be resolved by using plt.savefig instead of plt.show (cf. Save plot to image file instead of displaying it using Matplotlib) . But I don't want to change the program itself. The program may be given by other user who may familiar with using matplotlib in GUI environments.

So I consider to change the backend of matplotlib into my own backend which changes behavior of show. It can be done by changing matplotlibrc. But the document about backend only explains how to select "built-in" backends: https://matplotlib.org/faq/usage_faq.html?highlight=backend#coding-styles

The document says that backend can be specified as module://my_backend, but it does not define the "interface" of my_backend ( what kind of Classes/Object should be implemented in which names? )

Is there any documents which explains the interface of backends? (Or some other workaround change behavior of show?)

like image 721
hoge1e3 Avatar asked Sep 29 '19 06:09

hoge1e3


2 Answers

The most minimal backend could look like this, where we just take the figure canvas from the agg backend (and are hence able to use all associated methods)

from matplotlib.backend_bases import Gcf
from matplotlib.backends.backend_agg import FigureCanvasAgg

FigureCanvas = FigureCanvasAgg

def show(*args, **kwargs):
    for num, figmanager in enumerate(Gcf.get_all_fig_managers()):
        figmanager.canvas.figure.savefig(f"figure_{num}.png")

If you save this as mybackend.py, you can use it as backend via matplotlib.use("module://mybackend").

import matplotlib
matplotlib.use("module://mybackend")
import matplotlib.pyplot as plt

plt.figure()
plt.plot([1,3,2])

plt.figure()
plt.scatter([1,2,3], [3,2,3], color="crimson")

plt.show()
like image 65
ImportanceOfBeingErnest Avatar answered Oct 13 '22 22:10

ImportanceOfBeingErnest


I'm unfortunately having to create a separate answer, but this is really in addition to the accepted answer. You also need to create a FigureManager, or else you'll get a cryptic UserWarning: Matplotlib is currently using module://mybackend, which is a non-GUI backend, so cannot show the figure. if you try to show() a plt.fig(). My extra code thus far is this:

from matplotlib.backend_bases import FigureManagerBase

class FigureManager(FigureManagerBase):
    def show(self):
        self.canvas.figure.savefig('foo.png')
like image 27
Sébastien Loisel Avatar answered Oct 13 '22 22:10

Sébastien Loisel