8000 Merge pull request #12554 from anntzer/template · matplotlib/matplotlib@26290b0 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 26290b0

Browse files
authored
Merge pull request #12554 from anntzer/template
backend_template docs and fixes
2 parents 32a111b + 23f2c3b commit 26290b0

File tree

5 files changed

+54
-88
lines changed

5 files changed

+54
-88
lines changed

doc/api/backend_template_api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
:mod:`matplotlib.backends.backend_template`
3+
===========================================
4+
5+
.. automodule:: matplotlib.backends.backend_template
6+
:members:
7+
:undoc-members:
8+
:show-inheritance:

doc/api/index_backend_api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
:maxdepth: 1
77

88
backend_mixed_api.rst
9+
backend_template_api.rst
910
backend_agg_api.rst
1011
backend_cairo_api.rst
1112
backend_gtk3agg_api.rst

lib/matplotlib/backend_bases.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,10 @@ def _get_text_path_transform(self, x, y, s, prop, angle, ismath):
567567
path = Path(verts, codes)
568568
angle = np.deg2rad(angle)
569569
if self.flipy():
570+
width, height = self.get_canvas_width_height()
570571
transform = Affine2D().scale(fontsize / text2path.FONT_SCALE,
571572
fontsize / text2path.FONT_SCALE)
8000
572-
transform = transform.rotate(angle).translate(x, self.height - y)
573+
transform = transform.rotate(angle).translate(x, height - y)
573574
else:
574575
transform = Affine2D().scale(fontsize / text2path.FONT_SCALE,
575576
fontsize / text2path.FONT_SCALE)
@@ -2461,7 +2462,7 @@ class NonGuiException(Exception):
24612462

24622463
class FigureManagerBase:
24632464
"""
2464-
Helper class for pyplot mode, wraps everything up into a neat bundle
2465+
Helper class for pyplot mode, wraps everything up into a neat bundle.
24652466
24662467
Attributes
24672468
----------

lib/matplotlib/backends/backend_template.py

Lines changed: 40 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,32 @@
11
"""
2-
This is a fully functional do nothing backend to provide a template to
3-
backend writers. It is fully functional in that you can select it as
4-
a backend with
5-
6-
import matplotlib
7-
matplotlib.use('Template')
8-
9-
and your matplotlib scripts will (should!) run without error, though
10-
no output is produced. This provides a nice starting point for
11-
backend writers because you can selectively implement methods
12-
(draw_rectangle, draw_lines, etc...) and slowly see your figure come
13-
to life w/o having to have a full blown implementation before getting
14-
any results.
15-
16-
Copy this to backend_xxx.py and replace all instances of 'template'
17-
with 'xxx'. Then implement the class methods and functions below, and
18-
add 'xxx' to the switchyard in matplotlib/backends/__init__.py and
19-
'xxx' to the backends list in the validate_backend method in
20-
matplotlib/__init__.py and you're off. You can use your backend with::
21-
22-
import matplotlib
23-
matplotlib.use('xxx')
24-
import matplotlib.pyplot as plt
25-
plt.plot([1,2,3])
26-
plt.show()
27-
28-
matplotlib also supports external backends, so you can place you can
29-
use any module in your PYTHONPATH with the syntax::
30-
31-
import matplotlib
32-
matplotlib.use('module://my_backend')
33-
34-
where my_backend.py is your module name. This syntax is also
35-
recognized in the rc file and in the -d argument in pylab, e.g.,::
36-
37-
python simple_plot.py -dmodule://my_backend
38-
39-
If your backend implements support for saving figures (i.e. has a print_xyz()
40-
method) you can register it as the default handler for a given file type
41-
42-
from matplotlib.backend_bases import register_backend
43-
register_backend('xyz', 'my_backend', 'XYZ File Format')
44-
...
45-
plt.savefig("figure.xyz")
46-
47-
The files that are most relevant to backend_writers are
48-
49-
matplotlib/backends/backend_your_backend.py
50-
matplotlib/backend_bases.py
51-
matplotlib/backends/__init__.py
52-
matplotlib/__init__.py
53-
matplotlib/_pylab_helpers.py
54-
55-
Naming Conventions
56-
57-
* classes Upper or MixedUpperCase
58-
59-
* variables lower or lowerUpper
60-
61-
* functions lower or underscore_separated
62-
2+
This is a fully functional do nothing backend to provide a template to backend
3+
writers. It is fully functional in that you can select it as a backend e.g.
4+
with ::
5+
6+
import matplotlib
7+
matplotlib.use("template")
8+
9+
and your program will (should!) run without error, though no output is
10+
produced. This provides a starting point for backend writers; you can
11+
selectively implement drawing methods (`draw_path`, `draw_image`, etc.) and
12+
slowly see your figure come to life instead having to have a full blown
13+
implementation before getting any results.
14+
15+
Copy this file to a directory outside of the Matplotlib source tree, somewhere
16+
where Python can import it (by adding the directory to your ``sys.path`` or by
17+
packaging it as a normal Python package); if the backend is importable as
18+
``import my.backend`` you can then select it using ::
19+
20+
import matplotlib
21+
matplotlib.use("module://my.backend")
22+
23+
If your backend implements support for saving figures (i.e. has a `print_xyz`
24+
method), you can register it as the default handler for a given file type::
25+
26+
from matplotlib.backend_bases import register_backend
27+
register_backend('xyz', 'my_backend', 'XYZ File Format')
28+
...
29+
plt.savefig("figure.xyz")
6330
"""
6431

6532
from matplotlib._pylab_helpers import Gcf
@@ -73,10 +40,12 @@ class RendererTemplate(RendererBase):
7340
The renderer handles drawing/rendering operations.
7441
7542
This is a minimal do-nothing class that can be used to get started when
76-
writing a new backend. Refer to backend_bases.RendererBase for
77-
documentation of the classes methods.
43+
writing a new backend. Refer to `backend_bases.RendererBase` for
44+
documentation of the methods.
7845
"""
46+
7947
def __init__(self, dpi):
48+
super().__init__()
8049
self.dpi = dpi
8150

8251
def draw_path(self, gc, path, transform, rgbFace=None):
@@ -160,11 +129,12 @@ class GraphicsContextTemplate(GraphicsContextBase):
160129

161130
########################################################################
162131
#
163-
# The following functions and classes are for pylab and implement
132+
# The following functions and classes are for pyplot and implement
164133
# window/figure managers, etc...
165134
#
166135
########################################################################
167136

137+
168138
def draw_if_interactive():
169139
"""
170140
For image backends - is not required.
@@ -186,9 +156,7 @@ def show(*, block=None):
186156

187157

188158
def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
189-
"""
190-
Create a new figure manager instance
191-
"""
159+
"""Create a new figure manager instance."""
192160
# If a main-level app must be created, this (and
193161
# new_figure_manager_given_figure) is the usual place to do it -- see
194162
# backend_wx, backend_wxagg and backend_tkagg for examples. Not all GUIs
@@ -199,9 +167,7 @@ def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
199167

200168

201169
def new_figure_manager_given_figure(num, figure):
202-
"""
203-
Create a new figure manager instance for the given figure.
204-
"""
170+
"""Create a new figure manager instance for the given figure."""
205171
canvas = FigureCanvasTemplate(figure)
206172
manager = FigureManagerTemplate(canvas, num)
207173
return manager
@@ -225,9 +191,7 @@ class methods button_press_event, button_release_event,
225191
"""
226192

227193
def draw(self):
228-
"""
229-
Draw the figure using the renderer
230-
"""
194+
"""Draw the figure using the renderer."""
231195
renderer = RendererTemplate(self.figure.dpi)
232196
self.figure.draw(renderer)
233197

@@ -245,19 +209,18 @@ def print_foo(self, filename, *args, **kwargs):
245209
to their original values after this call, so you don't need to
246210
save and restore them.
247211
"""
248-
pass
249212

250213
def get_default_filetype(self):
251214
return 'foo' EED3
252215

253216

254217
class FigureManagerTemplate(FigureManagerBase):
255218
"""
256-
Wrap everything up into a window for the pylab interface
219+
Helper class for pyplot mode, wraps everything up into a neat bundle.
257220
258-
For non interactive backends, the base class does all the work
221+
For non-interactive backends, the base class is sufficient.
259222
"""
260-
pass
223+
261224

262225
########################################################################
263226
#

lib/matplotlib/patheffects.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ def __init__(self, path_effects, renderer):
9393
self._path_effects = path_effects
9494
self._renderer = renderer
9595

96-
def new_gc(self):
97-
# docstring inherited
98-
return self._renderer.new_gc()
99-
10096
def copy_with_path_effect(self, path_effects):
10197
return self.__class__(path_effects, self._renderer)
10298

@@ -143,10 +139,6 @@ def draw_path_collection(self, gc, master_transform, paths, *args,
143139
renderer.draw_path_collection(gc, master_transform, paths,
144140
*args, **kwargs)
145141

146-
def points_to_pixels(self, points):
147-
# docstring inherited
148-
return self._renderer.points_to_pixels(points)
149-
150142
def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath):
151143
# Implements the naive text drawing as is found in RendererBase.
152144
path, transform = self._get_text_path_transform(x, y, s, prop,
@@ -156,7 +148,8 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath):
156148
self.draw_path(gc, path, transform, rgbFace=color)
157149

158150
def __getattribute__(self, name):
159-
if name in ['_text2path', 'flipy', 'height', 'width']:
151+
if name in ['flipy', 'get_canvas_width_height', 'new_gc',
152+
'points_to_pixels', '_text2path', 'height', 'width']:
160153
return getattr(self._renderer, name)
161154
else:
162155
return object.__getattribute__(self, name)

0 commit comments

Comments
 (0)
0