8000 Merge pull request #2731 from matejak/2d-padding · matplotlib/matplotlib@4d53538 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4d53538

Browse files
committed
Merge pull request #2731 from matejak/2d-padding
2d padding
2 parents 3146413 + 0ea50bb commit 4d53538

File tree

5 files changed

+124
-51
lines changed

5 files changed

+124
-51
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2014-27-02 Implemented separate horizontal/vertical axes padding to the
2+
ImageGrid in the AxesGrid toolkit
3+
14
2014-01-02 `triplot` now returns the artist it adds and support of line and
25
marker kwargs has been improved. GBY
36

doc/api/api_changes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ original location:
139139
`fixed_dpi` parameter allows for overriding the `figure.dpi` setting
140140
instead of trying to deduce the intended behaviour from the file format.
141141

142+
* Added support for horizontal/vertical axes padding to
143+
`mpl_toolkits.axes_grid1.ImageGrid` --- argument ``axes_pad`` can now be
144+
tuple-like if separate axis padding is required.
145+
The original behavior is preserved.
146+
142147

143148
.. _changes_in_1_3:
144149

doc/users/whats_new.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ Added the `kwarg` 'which' to :func:`~matplotlib.Axes.get_xticklabels`,
114114
:func:`~matplotlib.Axis.set_ticks_position`. If 'which' is `None` then the old
115115
behaviour (controlled by the bool `minor`).
116116

117+
Separate horizontal/vertical axes padding support in ImageGrid
118+
``````````````````````````````````````````````````````````````
119+
The `kwarg` 'axes_pad' to :class:`mpl_toolkits.axes_grid1.ImageGrid` can now
120+
be a tuple if separate horizontal/vertical padding is needed.
121+
This is supposed to be very helpful when you have a labelled legend next to
122+
every subplot and you need to make some space for legend's labels.
123+
117124
Date handling
118125
-------------
119126

examples/axes_grid/demo_axes_grid.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def demo_simple_grid(fig):
1414
A grid of 2x2 images with 0.05 inch pad between images and only
1515
the lower-left axes is labeled.
1616
"""
17-
grid = AxesGrid(fig, 131, # similar to subplot(131)
17+
grid = AxesGrid(fig, 141, # similar to subplot(141)
1818
nrows_ncols = (2, 2),
1919
axes_pad = 0.05,
2020
label_mode = "1",
@@ -33,7 +33,7 @@ def demo_grid_with_single_cbar(fig):
3333
"""
3434
A grid of 2x2 images with a single colorbar
3535
"""
36-
grid = AxesGrid(fig, 132, # similar to subplot(132)
36+
grid = AxesGrid(fig, 142, # similar to subplot(142)
3737
nrows_ncols = (2, 2),
3838
axes_pad = 0.0,
3939
share_all=True,
@@ -61,7 +61,7 @@ def demo_grid_with_each_cbar(fig):
6161
A grid of 2x2 images. Each image has its own colorbar.
6262
"""
6363

64-
grid = AxesGrid(F, 133, # similar to subplot(122)
64+
grid = AxesGrid(F, 143, # similar to subplot(143)
6565
nrows_ncols = (2, 2),
6666
axes_pad = 0.1,
6767
label_mode = "1",
@@ -83,16 +83,47 @@ def demo_grid_with_each_cbar(fig):
8383
grid.axes_llc.set_xticks([-2, 0, 2])
8484
grid.axes_llc.set_yticks([-2, 0, 2])
8585

86+
def demo_grid_with_each_cbar_labelled(fig):
87+
"""
88+
A grid of 2x2 images. Each image has its own colorbar.
89+
"""
90+
91+
grid = AxesGrid(F, 144, # similar to subplot(144)
92+
nrows_ncols = (2, 2),
93+
axes_pad = ( 0.45, 0.15),
94+
label_mode = "1",
95+
share_all = True,
96+
cbar_location="right",
97+
cbar_mode="each",
98+
cbar_size="7%",
99+
cbar_pad="2%",
100+
)
101+
Z, extent = get_demo_image()
102+
103+
# Use a different colorbar range every time
104+
limits = ((0, 1), (-2, 2), (-1.7, 1.4), (-1.5, 1))
105+
for i in range(4):
106+
im = grid[i].imshow(Z, extent=extent, interpolation="nearest",
107+
vmin = limits[i][0], vmax = limits[i][1])
108+
grid.cbar_axes[i].colorbar(im)
109+
110+
for i, cax in enumerate(grid.cbar_axes):
111+
cax.set_yticks((limits[i][0], limits[i][1]))
112+
113+
# This affects all axes because we set share_all = True.
114+
grid.axes_llc.set_xticks([-2, 0, 2])
115+
grid.axes_llc.set_yticks([-2, 0, 2])
86116

87117

88118
if 1:
89-
F = plt.figure(1, (5.5, 2.5))
119+
F = plt.figure(1, (10.5, 2.5))
90120

91-
F.subplots_adjust(left=0.05, right=0.98)
121+
F.subplots_adjust(left=0.05, right=0.95)
92122

93123
demo_simple_grid(F)
94124
demo_grid_with_single_cbar(F)
95125
demo_grid_with_each_cbar(F)
126+
demo_grid_with_each_cbar_labelled(F)
96127

97128
plt.draw()
98129
plt.show()

lib/mpl_toolkits/axes_grid1/axes_grid.py

Lines changed: 73 additions & 46 deletions
10000
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@
1414
import matplotlib.lines as mlines
1515
import matplotlib.ticker as ticker
1616

17-
from matplotlib.gridspec import SubplotSpec, GridSpec
17+
from matplotlib.gridspec import SubplotSpec
1818

1919
from .axes_divider import Size, SubplotDivider, LocatableAxes, Divider
2020

2121

22+
def _extend_axes_pad(value):
23+
# Check whether a list/tuple/array or scalar has been passed
24+
ret = value
25+
if not hasattr(ret, "__getitem__"):
26+
ret = (value, value)
27+
return ret
28+
2229
def _tick_only(ax, bottom_on, left_on):
2330
bottom_off = not bottom_on
2431
left_off = not left_on
@@ -200,6 +207,8 @@ def __init__(self, fig,
200207
================ ======== =========================================
201208
direction "row" [ "row" | "column" ]
202209
axes_pad 0.02 float| pad between axes given in inches
210+
or tuple-like of floats,
211+
(horizontal padding, vertical padding)
203212
add_all True [ True | False ]
204213
share_all False [ True | False ]
205214
share_x True [ True | False ]
@@ -238,8 +247,8 @@ def __init__(self, fig,
238247
axes_class, axes_class_args = axes_class
239248

240249
self.axes_all = []
241-
self.axes_column = [[] for i in range(self._ncols)]
242-
self.axes_row = [[] for i in range(self._nrows)]
250+
self.axes_column = [[] for _ in range(self._ncols)]
251+
self.axes_row = [[] for _ in range(self._nrows)]
243252

244253
h = []
245254
v = []
@@ -261,8 +270,8 @@ def __init__(self, fig,
261270
rect = self._divider.get_position()
262271

263272
# reference axes
264-
self._column_refax = [None for i in range(self._ncols)]
265-
self._row_refax = [None for i in range(self._nrows)]
273+
self._column_refax = [None for _ in range(self._ncols)]
274+
self._row_refax = [None for _ in range(self._nrows)]
266275
self._refax = None
267276

268277
for i in range(self.ngrids):
@@ -310,19 +319,19 @@ def __init__(self, fig,
310319
self.set_label_mode(label_mode)
311320

312321
def _init_axes_pad(self, axes_pad):
322+
axes_pad = _extend_axes_pad(axes_pad)
313323
self._axes_pad = axes_pad
314324

315-
self._horiz_pad_size = Size.Fixed(axes_pad)
316-
self._vert_pad_size = Size.Fixed(axes_pad)
325+
self._horiz_pad_size = Size.Fixed(axes_pad[0])
326+
self._vert_pad_size = Size.Fixed(axes_pad[1])
317327

318328
def _update_locators(self):
319329

320330
h = []
321331

322332
h_ax_pos = []
323-
h_cb_pos = []
324333

325-
for ax in self._column_refax:
334+
for _ in self._column_refax:
326335
#if h: h.append(Size.Fixed(self._axes_pad))
327336
if h:
328337
h.append(self._horiz_pad_size)
@@ -335,8 +344,7 @@ def _update_locators(self):
335344
v = []
336345

337346
v_ax_pos = []
338-
v_cb_pos = []
339-
for ax in self._row_refax[::-1]:
347+
for _ in self._row_refax[::-1]:
340348
#if v: v.append(Size.Fixed(self._axes_pad))
341349
if v:
342350
v.append(self._vert_pad_size)
@@ -362,6 +370,10 @@ def _get_col_row(self, n):
362370

363371
return col, row
364372

373+
# Good to propagate __len__ if we have __getitem__
374+
def __len__(self):
375+
return len(self.axes_all)
376+
365377
def __getitem__(self, i):
366378
return self.axes_all[i]
367379

@@ -376,11 +388,19 @@ def set_axes_pad(self, axes_pad):
376388
"set axes_pad"
377389
self._axes_pad = axes_pad
378390

379-
self._horiz_pad_size.fixed_size = axes_pad
380-
self._vert_pad_size.fixed_size = axes_pad
391+
# These two lines actually differ from ones in _init_axes_pad
392+
self._horiz_pad_size.fixed_size = axes_pad[0]
393+
self._vert_pad_size.fixed_size = axes_pad[1]
381394

382395
def get_axes_pad(self):
383-
"get axes_pad"
396+
"""
397+
get axes_pad
398+
399+
Returns
400+
-------
401+
tuple
402+
Padding in inches, (horizontal pad, vertical pad)
403+
"""
384404
return self._axes_pad
385405

386406
def set_aspect(self, aspect):
@@ -484,6 +504,8 @@ def __init__(self, fig,
484504
================ ======== =========================================
485505
direction "row" [ "row" | "column" ]
486506
axes_pad 0.02 float| pad between axes given in inches
507+
or tuple-like of floats,
508+
(horizontal padding, vertical padding)
487509
add_all True [ True | False ]
488510
share_all False [ True | False ]
489511
aspect True [ True | False ]
@@ -510,12 +532,17 @@ def __init__(self, fig,
510532

511533
self.ngrids = ngrids
512534

535+
axes_pad = _extend_axes_pad(axes_pad)
513536
self._axes_pad = axes_pad
514537

515538
self._colorbar_mode = cbar_mode
516539
self._colorbar_location = cbar_location
517540
if cbar_pad is None:
518-
self._colorbar_pad = axes_pad
541+
# horizontal or vertical arrangement?
542+
if cbar_location in ("left", "right"):
543+
self._colorbar_pad = axes_pad[0]
544+
else:
545+
self._colorbar_pad = axes_pad[1]
519546
else:
520547
self._colorbar_pad = cbar_pad
521548

@@ -538,8 +565,8 @@ def __init__(self, fig,
538565
axes_class, axes_class_args = axes_class
539566

540567
self.axes_all = []
541-
self.axes_column = [[] for i in range(self._ncols)]
542-
self.axes_row = [[] for i in range(self._nrows)]
568+
self.axes_column = [[] for _ in range(self._ncols)]
569+
self.axes_row = [[] for _ in range(self._nrows)]
543570

544571
self.cbar_axes = []
545572

@@ -563,8 +590,8 @@ def __init__(self, fig,
563590
rect = self._divider.get_position()
564591

565592
# reference axes
566-
self._column_refax = [None for i in range(self._ncols)]
567-
self._row_refax = [None for i in range(self._nrows)]
593+
self._column_refax = [None for _ in range(self._ncols)]
594+
self._row_refax = [None for _ in range(self._nrows)]
568595
self._refax = None
569596

570597
for i in range(self.ngrids):
@@ -678,7 +705,7 @@ def _update_locators(self):
678705
v_cb_pos = []
679706
for row, ax in enumerate(self.axes_column[0][::-1]):
680707
if v:
681-
v.append(self._horiz_pad_size) # Size.Fixed(self._axes_pad))
708+
v.append(self._vert_pad_size) # Size.Fixed(self._axes_pad))
682709

683710
if ax:
684711
sz = Size.AxesY(ax, aspect="axes", ref_ax=self.axes_all[0])
@@ -786,7 +813,7 @@ def _update_locators(self):
786813
F.subplots_adjust(left=0.15, right=0.9)
787814

788815
grid = Grid(F, 111, # similar to subplot(111)
789-
nrows_ncols = (2, 2),
816+
nrows_ncols=(2, 2),
790817
direction="row",
791818
axes_pad = 0.05,
792819
add_all=True,
@@ -802,12 +829,12 @@ def _update_locators(self):
802829
F.subplots_adjust(left=0.05, right=0.98)
803830

804831
grid = ImageGrid(F, 131, # similar to subplot(111)
805-
nrows_ncols=(2, 2),
806-
direction="row",
807-
axes_pad = 0.05,
808-
add_all=True,
809-
label_mode = "1",
810-
)
832+
nrows_ncols=(2, 2),
833+
direction="row",
834+
axes_pad = 0.05,
835+
add_all=True,
836+
label_mode = "1",
837+
)
811838

812839
Z, extent = get_demo_image()
813840
plt.ioff()
@@ -821,14 +848,14 @@ def _update_locators(self):
821848
plt.ion()
822849

823850
grid = ImageGrid(F, 132, # similar to subplot(111)
824-
nrows_ncols=(2, 2),
825-
direction="row",
826-
axes_pad = 0.0,
827-
add_all=True,
828-
share_all=True,
829-
label_mode = "1",
830-
cbar_mode="single",
831-
)
851+
nrows_ncols=(2, 2),
852+
direction="row",
853+
axes_pad = 0.0,
854+
add_all=True,
855+
share_all=True,
856+
label_mode = "1",
857+
cbar_mode="single",
858+
)
832859

833860
Z, extent = get_demo_image()
834861
plt.ioff()
@@ -844,17 +871,17 @@ def _update_locators(self):
844871
plt.ion()
845872

846873
grid = ImageGrid(F, 133, # similar to subplot(122)
847-
nrows_ncols=(2, 2),
848-
direction="row",
849-
axes_pad = 0.1,
850-
add_all=True,
851-
label_mode = "1",
852-
share_all = True,
853-
cbar_location="top",
854-
cbar_mode="each",
855-
cbar_size="7%",
856-
cbar_pad="2%",
857-
)
874+
nrows_ncols=(2, 2),
875+
direction="row",
876+
axes_pad = 0.1,
877+
add_all=True,
878+
label_mode = "1",
879+
share_all = True,
880+
cbar_location="top",
881+
cbar_mode="each",
882+
cbar_size="7%",
883+
cbar_pad="2%",
884+
)
858885
plt.ioff()
859886
for i in range(4):
860887
im = grid[i].imshow(Z, extent=extent, interpolation="nearest")

0 commit comments

Comments
 (0)
0