hoge1e3
hoge1e3

Reputation: 836

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?)

Upvotes: 5

Views: 1191

Answers (3)

DamonJW
DamonJW

Reputation: 3662

You also asked if there's any documentation that explains the backend interface.

There is: there's a backend called 'template' in the matplotlib source code, with comments that describe the interface.

https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/backends/backend_template.py

Upvotes: 1

Sébastien Loisel
Sébastien Loisel

Reputation: 546

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')

Upvotes: 1

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339052

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()

Upvotes: 4

Related Questions