FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
matplotlib/lib/matplotlib/layout_engine.py at v3.11.2 · matplotlib/matplotlib · GitHub
matplotlib
/
matplotlib
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
8.5k
Star
23.3k
Code
Issues
1.1k
Pull requests
432
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
matplotlib
/
lib
/
matplotlib
/
layout_engine.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
309 lines (260 loc) · 11.2 KB
Breadcrumbs
matplotlib
/
lib
/
matplotlib
/
layout_engine.py
Copy path
File metadata and controls
309 lines (260 loc) · 11.2 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
"""
Classes to layout elements in a `.Figure`.
Figures have a ``layout_engine`` property that holds a subclass of
`~.LayoutEngine` defined here (or *None* for no layout). At draw time
``figure.get_layout_engine().execute()`` is called, the goal of which is
usually to rearrange Axes on the figure to produce a pleasing layout. This is
like a ``draw`` callback but with two differences. First, when printing we
disable the layout engine for the final draw. Second, it is useful to know the
layout engine while the figure is being created. In particular, colorbars are
made differently with different layout engines (for historical reasons).
Matplotlib has two built-in layout engines:
- `.TightLayoutEngine` was the first layout engine added to Matplotlib.
See also :ref:`tight_layout_guide`.
- `.ConstrainedLayoutEngine` is more modern and generally gives better results.
See also :ref:`constrainedlayout_guide`.
Third parties can create their own layout engine by subclassing `.LayoutEngine`.
"""
from
contextlib
import
nullcontext
import
matplotlib
as
mpl
from
matplotlib
.
_constrained_layout
import
do_constrained_layout
from
matplotlib
.
_tight_layout
import
(
get_subplotspec_list
,
get_tight_layout_figure
)
class
LayoutEngine
:
"""
Base class for Matplotlib layout engines.
A layout engine can be passed to a figure at instantiation or at any time
with `~.figure.Figure.set_layout_engine`. Once attached to a figure, the
layout engine ``execute`` function is called at draw time by
`~.figure.Figure.draw`, providing a special draw-time hook.
.. note::
However, note that layout engines affect the creation of colorbars, so
`~.figure.Figure.set_layout_engine` should be called before any
colorbars are created.
Currently, there are two properties of `LayoutEngine` classes that are
consulted while manipulating the figure:
- ``engine.colorbar_gridspec`` tells `.Figure.colorbar` whether to make the
axes using the gridspec method (see `.colorbar.make_axes_gridspec`) or
not (see `.colorbar.make_axes`);
- ``engine.adjust_compatible`` stops `.Figure.subplots_adjust` from being
run if it is not compatible with the layout engine.
To implement a custom `LayoutEngine`:
1. override ``_adjust_compatible`` and ``_colorbar_gridspec``
2. override `LayoutEngine.set` to update *self._params*
3. override `LayoutEngine.execute` with your implementation
"""
# override these in subclass
_adjust_compatible
=
None
_colorbar_gridspec
=
None
def
__init__
(
self
,
**
kwargs
):
super
().
__init__
(
**
kwargs
)
self
.
_params
=
{}
def
set
(
self
,
**
kwargs
):
"""
Set the parameters for the layout engine.
"""
raise
NotImplementedError
@
property
def
colorbar_gridspec
(
self
):
"""
Return a boolean if the layout engine creates colorbars using a
gridspec.
"""
if
self
.
_colorbar_gridspec
is
None
:
raise
NotImplementedError
return
self
.
_colorbar_gridspec
@
property
def
adjust_compatible
(
self
):
"""
Return a boolean if the layout engine is compatible with
`~.Figure.subplots_adjust`.
"""
if
self
.
_adjust_compatible
is
None
:
raise
NotImplementedError
return
self
.
_adjust_compatible
def
get
(
self
):
"""
Return copy of the parameters for the layout engine.
"""
return
dict
(
self
.
_params
)
def
execute
(
self
,
fig
):
"""
Execute the layout on the figure given by *fig*.
"""
# subclasses must implement this.
raise
NotImplementedError
class
PlaceHolderLayoutEngine
(
LayoutEngine
):
"""
This layout engine does not adjust the figure layout at all.
The purpose of this `.LayoutEngine` is to act as a placeholder when the user removes
a layout engine to ensure an incompatible `.LayoutEngine` cannot be set later.
Parameters
----------
adjust_compatible, colorbar_gridspec : bool
Allow the PlaceHolderLayoutEngine to mirror the behavior of whatever
layout engine it is replacing.
"""
def
__init__
(
self
,
adjust_compatible
,
colorbar_gridspec
,
**
kwargs
):
self
.
_adjust_compatible
=
adjust_compatible
self
.
_colorbar_gridspec
=
colorbar_gridspec
super
().
__init__
(
**
kwargs
)
def
execute
(
self
,
fig
):
"""
Do nothing.
"""
return
class
TightLayoutEngine
(
LayoutEngine
):
"""
Implements the ``tight_layout`` geometry management. See
:ref:`tight_layout_guide` for details.
"""
_adjust_compatible
=
True
_colorbar_gridspec
=
True
def
__init__
(
self
,
*
,
pad
=
1.08
,
h_pad
=
None
,
w_pad
=
None
,
rect
=
(
0
,
0
,
1
,
1
),
**
kwargs
):
"""
Initialize tight_layout engine.
Parameters
----------
pad : float, default: 1.08
Padding between the figure edge and the edges of subplots, as a
fraction of the font size.
h_pad, w_pad : float
Padding (height/width) between edges of adjacent subplots.
Defaults to *pad*.
rect : tuple (left, bottom, right, top), default: (0, 0, 1, 1).
rectangle in normalized figure coordinates that the subplots
(including labels) will fit into.
"""
super
().
__init__
(
**
kwargs
)
for
td
in
[
'pad'
,
'h_pad'
,
'w_pad'
,
'rect'
]:
# initialize these in case None is passed in above:
self
.
_params
[
td
]
=
None
self
.
set
(
pad
=
pad
,
h_pad
=
h_pad
,
w_pad
=
w_pad
,
rect
=
rect
)
def
execute
(
self
,
fig
):
"""
Execute tight_layout.
This decides the subplot parameters given the padding that
will allow the Axes labels to not be covered by other labels
and Axes.
Parameters
----------
fig : `.Figure` to perform layout on.
See Also
--------
.figure.Figure.tight_layout
.pyplot.tight_layout
"""
info
=
self
.
_params
renderer
=
fig
.
_get_renderer
()
with
getattr
(
renderer
,
"_draw_disabled"
,
nullcontext
)():
kwargs
=
get_tight_layout_figure
(
fig
,
fig
.
axes
,
get_subplotspec_list
(
fig
.
axes
),
renderer
,
pad
=
info
[
'pad'
],
h_pad
=
info
[
'h_pad'
],
w_pad
=
info
[
'w_pad'
],
rect
=
info
[
'rect'
])
if
kwargs
:
fig
.
subplots_adjust
(
**
kwargs
)
def
set
(
self
,
*
,
pad
=
None
,
w_pad
=
None
,
h_pad
=
None
,
rect
=
None
):
"""
Set the pads for tight_layout.
Parameters
----------
pad : float
Padding between the figure edge and the edges of subplots, as a
fraction of the font size.
w_pad, h_pad : float
Padding (width/height) between edges of adjacent subplots.
Defaults to *pad*.
rect : tuple (left, bottom, right, top)
rectangle in normalized figure coordinates that the subplots
(including labels) will fit into.
"""
for
td
in
self
.
set
.
__kwdefaults__
:
if
locals
()[
td
]
is
not
None
:
self
.
_params
[
td
]
=
locals
()[
td
]
class
ConstrainedLayoutEngine
(
LayoutEngine
):
"""
Implements the ``constrained_layout`` geometry management. See
:ref:`constrainedlayout_guide` for details.
"""
_adjust_compatible
=
False
_colorbar_gridspec
=
False
def
__init__
(
self
,
*
,
h_pad
=
None
,
w_pad
=
None
,
hspace
=
None
,
wspace
=
None
,
rect
=
(
0
,
0
,
1
,
1
),
compress
=
False
,
**
kwargs
):
"""
Initialize ``constrained_layout`` settings.
Parameters
----------
h_pad, w_pad : float
Padding around the Axes elements in inches.
Default to :rc:`figure.constrained_layout.h_pad` and
:rc:`figure.constrained_layout.w_pad`.
hspace, wspace : float
Fraction of the figure to dedicate to space between the
axes. These are evenly spread between the gaps between the Axes.
A value of 0.2 for a three-column layout would have a space
of 0.1 of the figure width between each column.
If h/wspace < h/w_pad, then the pads are used instead.
Default to :rc:`figure.constrained_layout.hspace` and
:rc:`figure.constrained_layout.wspace`.
rect : tuple of 4 floats
Rectangle in figure coordinates to perform constrained layout in
(left, bottom, width, height), each from 0-1.
compress : bool
Whether to shift Axes so that white space in between them is
removed. This is useful for simple grids of fixed-aspect Axes (e.g.
a grid of images). See :ref:`compressed_layout`.
"""
super
().
__init__
(
**
kwargs
)
# set the defaults:
self
.
set
(
w_pad
=
mpl
.
rcParams
[
'figure.constrained_layout.w_pad'
],
h_pad
=
mpl
.
rcParams
[
'figure.constrained_layout.h_pad'
],
wspace
=
mpl
.
rcParams
[
'figure.constrained_layout.wspace'
],
hspace
=
mpl
.
rcParams
[
'figure.constrained_layout.hspace'
],
rect
=
(
0
,
0
,
1
,
1
))
# set anything that was passed in (None will be ignored):
self
.
set
(
w_pad
=
w_pad
,
h_pad
=
h_pad
,
wspace
=
wspace
,
hspace
=
hspace
,
rect
=
rect
)
self
.
_compress
=
compress
def
execute
(
self
,
fig
):
"""
Perform constrained_layout and move and resize Axes accordingly.
Parameters
----------
fig : `.Figure` to perform layout on.
"""
width
,
height
=
fig
.
get_size_inches
()
# pads are relative to the current state of the figure...
w_pad
=
self
.
_params
[
'w_pad'
]
/
width
h_pad
=
self
.
_params
[
'h_pad'
]
/
height
return
do_constrained_layout
(
fig
,
w_pad
=
w_pad
,
h_pad
=
h_pad
,
wspace
=
self
.
_params
[
'wspace'
],
hspace
=
self
.
_params
[
'hspace'
],
rect
=
self
.
_params
[
'rect'
],
compress
=
self
.
_compress
)
def
set
(
self
,
*
,
h_pad
=
None
,
w_pad
=
None
,
hspace
=
None
,
wspace
=
None
,
rect
=
None
):
"""
Set the pads for constrained_layout.
Parameters
----------
h_pad, w_pad : float
Padding around the Axes elements in inches.
Default to :rc:`figure.constrained_layout.h_pad` and
:rc:`figure.constrained_layout.w_pad`.
hspace, wspace : float
Fraction of the figure to dedicate to space between the
axes. These are evenly spread between the gaps between the Axes.
A value of 0.2 for a three-column layout would have a space
of 0.1 of the figure width between each column.
If h/wspace < h/w_pad, then the pads are used instead.
Default to :rc:`figure.constrained_layout.hspace` and
:rc:`figure.constrained_layout.wspace`.
rect : tuple of 4 floats
Rectangle in figure coordinates to perform constrained layout in
(left, bottom, width, height), each from 0-1.
"""
for
td
in
self
.
set
.
__kwdefaults__
:
if
locals
()[
td
]
is
not
None
:
self
.
_params
[
td
]
=
locals
()[
td
]
Back
|
FazBrowse Home
|
New Git URL