Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit acae2c4

Browse files
committed
ENH: add rect parameter to constrained_layout
1 parent 698397f commit acae2c4

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

lib/matplotlib/_constrained_layout.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
######################################################
6666
def do_constrained_layout(fig, h_pad, w_pad,
67-
hspace=None, wspace=None):
67+
hspace=None, wspace=None, rect=(0, 0, 1, 1)):
6868
"""
6969
Do the constrained_layout. Called at draw time in
7070
``figure.constrained_layout()``
@@ -87,14 +87,18 @@ def do_constrained_layout(fig, h_pad, w_pad,
8787
of 0.1 of the figure width between each column.
8888
If h/wspace < h/w_pad, then the pads are used instead.
8989
90+
rect : tuple of 4 floats
91+
Rectangle in figure coordinates to perform constrained layout in
92+
[left, bottom, width, height], each from 0-1.
93+
9094
Returns
9195
-------
9296
layoutgrid : private debugging structure
9397
"""
9498

9599
renderer = _get_renderer(fig)
96100
# make layoutgrid tree...
97-
layoutgrids = make_layoutgrids(fig, None)
101+
layoutgrids = make_layoutgrids(fig, None, rect=rect)
98102
if not layoutgrids['hasgrids']:
99103
_api.warn_external('There are no gridspecs with layoutgrids. '
100104
'Possibly did not call parent GridSpec with the'
@@ -133,7 +137,7 @@ def do_constrained_layout(fig, h_pad, w_pad,
133137
return layoutgrids
134138

135139

136-
def make_layoutgrids(fig, layoutgrids):
140+
def make_layoutgrids(fig, layoutgrids, rect=[0, 0, 1, 1]):
137141
"""
138142
Make the layoutgrid tree.
139143
@@ -147,8 +151,9 @@ def make_layoutgrids(fig, layoutgrids):
147151
layoutgrids = dict()
148152
layoutgrids['hasgrids'] = False
149153
if not hasattr(fig, '_parent'):
150-
# top figure
151-
layoutgrids[fig] = mlayoutgrid.LayoutGrid(parent=None, name='figlb')
154+
# top figure; pass rect as parent to allow user-specified
155+
# margins
156+
layoutgrids[fig] = mlayoutgrid.LayoutGrid(parent=rect, name='figlb')
152157
else:
153158
# subfigure
154159
gs = fig._subplotspec.get_gridspec()

lib/matplotlib/_layoutgrid.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def __init__(self, parent=None, parent_pos=(0, 0),
3939
self.parent_pos = parent_pos
4040
self.parent_inner = parent_inner
4141
self.name = name + seq_id()
42-
if parent is not None:
42+
if isinstance(parent, LayoutGrid):
4343
self.name = f'{parent.name}.{self.name}'
4444
self.nrows = nrows
4545
self.ncols = ncols
@@ -51,8 +51,10 @@ def __init__(self, parent=None, parent_pos=(0, 0),
5151
self.width_ratios = np.ones(ncols)
5252

5353
sn = self.name + '_'
54-
if parent is None:
55-
self.parent = None
54+
if not isinstance(parent, LayoutGrid):
55+
# parent can be a rect if not a LayoutGrid
56+
# allows specifying a rectangle to contain the layout.
57+
self.parent = parent
5658
self.solver = kiwi.Solver()
5759
else:
5860
self.parent = parent
@@ -178,12 +180,13 @@ def parent_constraints(self):
178180
# parent's left, the last column right equal to the
179181
# parent's right...
180182
parent = self.parent
181-
if parent is None:
182-
hc = [self.lefts[0] == 0,
183-
self.rights[-1] == 1,
183+
if not isinstance(parent, LayoutGrid):
184+
# specify a rectangle in figure coordinates
185+
hc = [self.lefts[0] == parent[0],
186+
self.rights[-1] == parent[0] + parent[2],
184187
# top and bottom reversed order...
185-
self.tops[0] == 1,
186-
self.bottoms[-1] == 0]
188+
self.tops[0] == parent[1] + parent[3],
189+
self.bottoms[-1] == parent[1]]
187190
else:
188191
rows, cols = self.parent_pos
189192
rows = np.atleast_1d(rows)

lib/matplotlib/layout_engine.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ class ConstrainedLayoutEngine(LayoutEngine):
178178
_colorbar_gridspec = False
179179

180180
def __init__(self, *, h_pad=None, w_pad=None,
181-
hspace=None, wspace=None, **kwargs):
181+
hspace=None, wspace=None, rect=[0, 0, 1, 1],
182+
**kwargs):
182183
"""
183184
Initialize ``constrained_layout`` settings.
184185
@@ -196,15 +197,20 @@ def __init__(self, *, h_pad=None, w_pad=None,
196197
If h/wspace < h/w_pad, then the pads are used instead.
197198
Default to :rc:`figure.constrained_layout.hspace` and
198199
:rc:`figure.constrained_layout.wspace`.
200+
rect : [l, b, w, h]
201+
Rectangle in figure coordinates to perform constrained layout in
202+
[left, bottom, width, height], each from 0-1.
199203
"""
200204
super().__init__(**kwargs)
201205
# set the defaults:
202206
self.set(w_pad=mpl.rcParams['figure.constrained_layout.w_pad'],
203207
h_pad=mpl.rcParams['figure.constrained_layout.h_pad'],
204208
wspace=mpl.rcParams['figure.constrained_layout.wspace'],
205-
hspace=mpl.rcParams['figure.constrained_layout.hspace'])
209+
hspace=mpl.rcParams['figure.constrained_layout.hspace'],
210+
rect=[0, 0, 1, 1])
206211
# set anything that was passed in (None will be ignored):
207-
self.set(w_pad=w_pad, h_pad=h_pad, wspace=wspace, hspace=hspace)
212+
self.set(w_pad=w_pad, h_pad=h_pad, wspace=wspace, hspace=hspace,
213+
rect=rect)
208214

209215
def execute(self, fig):
210216
"""
@@ -221,10 +227,11 @@ def execute(self, fig):
221227

222228
return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
223229
wspace=self._params['wspace'],
224-
hspace=self._params['hspace'])
230+
hspace=self._params['hspace'],
231+
rect=self._params['rect'])
225232

226233
def set(self, *, h_pad=None, w_pad=None,
227-
hspace=None, wspace=None):
234+
hspace=None, wspace=None, rect=None):
228235
"""
229236
Set the pads for constrained_layout.
230237
@@ -242,6 +249,9 @@ def set(self, *, h_pad=None, w_pad=None,
242249
If h/wspace < h/w_pad, then the pads are used instead.
243250
Default to :rc:`figure.constrained_layout.hspace` and
244251
:rc:`figure.constrained_layout.wspace`.
252+
rect : [l, b, w, h]
253+
Rectangle in figure coordinates to perform constrained layout in
254+
[left, bottom, width, height], each from 0-1.
245255
"""
246256
for td in self.set.__kwdefaults__:
247257
if locals()[td] is not None:

lib/matplotlib/tests/test_constrainedlayout.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,3 +608,21 @@ def test_discouraged_api():
608608
def test_kwargs():
609609
fig, ax = plt.subplots(constrained_layout={'h_pad': 0.02})
610610
fig.draw_without_rendering()
611+
612+
613+
def test_rect():
614+
fig, ax = plt.subplots(layout='constrained')
615+
fig.get_layout_engine().set(rect=[0, 0, 0.5, 0.5])
616+
fig.draw_without_rendering()
617+
ppos = ax.get_position()
618+
assert ppos.x1 < 0.5
619+
assert ppos.y1 < 0.5
620+
621+
fig, ax = plt.subplots(layout='constrained')
622+
fig.get_layout_engine().set(rect=[0.2, 0.2, 0.3, 0.3])
623+
fig.draw_without_rendering()
624+
ppos = ax.get_position()
625+
assert ppos.x1 < 0.5
626+
assert ppos.y1 < 0.5
627+
assert ppos.x0 > 0.2
628+
assert ppos.y0 > 0.2

0 commit comments

Comments
 (0)