Skip to content

2d padding #2731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2014-27-02 Implemented separate horizontal/vertical axes padding to the
ImageGrid in the AxesGrid toolkit

2014-01-02 `triplot` now returns the artist it adds and support of line and
marker kwargs has been improved. GBY

Expand Down
5 changes: 5 additions & 0 deletions doc/api/api_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ original location:
`fixed_dpi` parameter allows for overriding the `figure.dpi` setting
instead of trying to deduce the intended behaviour from the file format.

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


.. _changes_in_1_3:

Expand Down
7 changes: 7 additions & 0 deletions doc/users/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ Added the `kwarg` 'which' to :func:`~matplotlib.Axes.get_xticklabels`,
:func:`~matplotlib.Axis.set_ticks_position`. If 'which' is `None` then the old
behaviour (controlled by the bool `minor`).

Separate horizontal/vertical axes padding support in ImageGrid
``````````````````````````````````````````````````````````````
The `kwarg` 'axes_pad' to :class:`mpl_toolkits.axes_grid1.ImageGrid` can now
be a tuple if separate horizontal/vertical padding is needed.
This is supposed to be very helpful when you have a labelled legend next to
every subplot and you need to make some space for legend's labels.

Date handling
-------------

Expand Down
41 changes: 36 additions & 5 deletions examples/axes_grid/demo_axes_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def demo_simple_grid(fig):
A grid of 2x2 images with 0.05 inch pad between images and only
the lower-left axes is labeled.
"""
grid = AxesGrid(fig, 131, # similar to subplot(131)
grid = AxesGrid(fig, 141, # similar to subplot(141)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these changes here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never mind, I understand now, sorry for the spam.

nrows_ncols = (2, 2),
axes_pad = 0.05,
label_mode = "1",
Expand All @@ -33,7 +33,7 @@ def demo_grid_with_single_cbar(fig):
"""
A grid of 2x2 images with a single colorbar
"""
grid = AxesGrid(fig, 132, # similar to subplot(132)
grid = AxesGrid(fig, 142, # similar to subplot(142)
nrows_ncols = (2, 2),
axes_pad = 0.0,
share_all=True,
Expand Down Expand Up @@ -61,7 +61,7 @@ def demo_grid_with_each_cbar(fig):
A grid of 2x2 images. Each image has its own colorbar.
"""

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

def demo_grid_with_each_cbar_labelled(fig):
"""
A grid of 2x2 images. Each image has its own colorbar.
"""

grid = AxesGrid(F, 144, # similar to subplot(144)
nrows_ncols = (2, 2),
axes_pad = ( 0.45, 0.15),
label_mode = "1",
share_all = True,
cbar_location="right",
cbar_mode="each",
cbar_size="7%",
cbar_pad="2%",
)
Z, extent = get_demo_image()

# Use a different colorbar range every time
limits = ((0, 1), (-2, 2), (-1.7, 1.4), (-1.5, 1))
for i in range(4):
im = grid[i].imshow(Z, extent=extent, interpolation="nearest",
vmin = limits[i][0], vmax = limits[i][1])
grid.cbar_axes[i].colorbar(im)

for i, cax in enumerate(grid.cbar_axes):
cax.set_yticks((limits[i][0], limits[i][1]))

# This affects all axes because we set share_all = True.
grid.axes_llc.set_xticks([-2, 0, 2])
grid.axes_llc.set_yticks([-2, 0, 2])


if 1:
F = plt.figure(1, (5.5, 2.5))
F = plt.figure(1, (10.5, 2.5))

F.subplots_adjust(left=0.05, right=0.98)
F.subplots_adjust(left=0.05, right=0.95)

demo_simple_grid(F)
demo_grid_with_single_cbar(F)
demo_grid_with_each_cbar(F)
demo_grid_with_each_cbar_labelled(F)

plt.draw()
plt.show()
Expand Down
119 changes: 73 additions & 46 deletions lib/mpl_toolkits/axes_grid1/axes_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@
import matplotlib.lines as mlines
import matplotlib.ticker as ticker

from matplotlib.gridspec import SubplotSpec, GridSpec
from matplotlib.gridspec import SubplotSpec

from .axes_divider import Size, SubplotDivider, LocatableAxes, Divider


def _extend_axes_pad(value):
# Check whether a list/tuple/array or scalar has been passed
ret = value
if not hasattr(ret, "__getitem__"):
ret = (value, value)
return ret

def _tick_only(ax, bottom_on, left_on):
bottom_off = not bottom_on
left_off = not left_on
Expand Down Expand Up @@ -200,6 +207,8 @@ def __init__(self, fig,
================ ======== =========================================
direction "row" [ "row" | "column" ]
axes_pad 0.02 float| pad between axes given in inches
or tuple-like of floats,
(horizontal padding, vertical padding)
add_all True [ True | False ]
share_all False [ True | False ]
share_x True [ True | False ]
Expand Down Expand Up @@ -238,8 +247,8 @@ def __init__(self, fig,
axes_class, axes_class_args = axes_class

self.axes_all = []
self.axes_column = [[] for i in range(self._ncols)]
self.axes_row = [[] for i in range(self._nrows)]
self.axes_column = [[] for _ in range(self._ncols)]
self.axes_row = [[] for _ in range(self._nrows)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the variable change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because i is not used in the expression, I have replaced it with _, which is considered as a "throw-away" variable identifier (see for instance http://stackoverflow.com/questions/1739514/as-variable-name-in-python)


h = []
v = []
Expand All @@ -261,8 +270,8 @@ def __init__(self, fig,
rect = self._divider.get_position()

# reference axes
self._column_refax = [None for i in range(self._ncols)]
self._row_refax = [None for i in range(self._nrows)]
self._column_refax = [None for _ in range(self._ncols)]
self._row_refax = [None for _ in range(self._nrows)]
self._refax = None

for i in range(self.ngrids):
Expand Down Expand Up @@ -310,19 +319,19 @@ def __init__(self, fig,
self.set_label_mode(label_mode)

def _init_axes_pad(self, axes_pad):
axes_pad = _extend_axes_pad(axes_pad)
self._axes_pad = axes_pad

self._horiz_pad_size = Size.Fixed(axes_pad)
self._vert_pad_size = Size.Fixed(axes_pad)
self._horiz_pad_size = Size.Fixed(axes_pad[0])
self._vert_pad_size = Size.Fixed(axes_pad[1])

def _update_locators(self):

h = []

h_ax_pos = []
h_cb_pos = []

for ax in self._column_refax:
for _ in self._column_refax:
#if h: h.append(Size.Fixed(self._axes_pad))
if h:
h.append(self._horiz_pad_size)
Expand All @@ -335,8 +344,7 @@ def _update_locators(self):
v = []

v_ax_pos = []
v_cb_pos = []
for ax in self._row_refax[::-1]:
for _ in self._row_refax[::-1]:
#if v: v.append(Size.Fixed(self._axes_pad))
if v:
v.append(self._vert_pad_size)
Expand All @@ -362,6 +370,10 @@ def _get_col_row(self, n):

return col, row

# Good to propagate __len__ if we have __getitem__
def __len__(self):
return len(self.axes_all)

def __getitem__(self, i):
return self.axes_all[i]

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

self._horiz_pad_size.fixed_size = axes_pad
self._vert_pad_size.fixed_size = axes_pad
# These two lines actually differ from ones in _init_axes_pad
self._horiz_pad_size.fixed_size = axes_pad[0]
self._vert_pad_size.fixed_size = axes_pad[1]

def get_axes_pad(self):
"get axes_pad"
"""
get axes_pad

Returns
-------
tuple
Padding in inches, (horizontal pad, vertical pad)
"""
return self._axes_pad

def set_aspect(self, aspect):
Expand Down Expand Up @@ -484,6 +504,8 @@ def __init__(self, fig,
================ ======== =========================================
direction "row" [ "row" | "column" ]
axes_pad 0.02 float| pad between axes given in inches
or tuple-like of floats,
(horizontal padding, vertical padding)
add_all True [ True | False ]
share_all False [ True | False ]
aspect True [ True | False ]
Expand All @@ -510,12 +532,17 @@ def __init__(self, fig,

self.ngrids = ngrids

axes_pad = _extend_axes_pad(axes_pad)
self._axes_pad = axes_pad

self._colorbar_mode = cbar_mode
self._colorbar_location = cbar_location
if cbar_pad is None:
self._colorbar_pad = axes_pad
# horizontal or vertical arrangement?
if cbar_location in ("left", "right"):
self._colorbar_pad = axes_pad[0]
else:
self._colorbar_pad = axes_pad[1]
else:
self._colorbar_pad = cbar_pad

Expand All @@ -538,8 +565,8 @@ def __init__(self, fig,
axes_class, axes_class_args = axes_class

self.axes_all = []
self.axes_column = [[] for i in range(self._ncols)]
self.axes_row = [[] for i in range(self._nrows)]
self.axes_column = [[] for _ in range(self._ncols)]
self.axes_row = [[] for _ in range(self._nrows)]

self.cbar_axes = []

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

# reference axes
self._column_refax = [None for i in range(self._ncols)]
self._row_refax = [None for i in range(self._nrows)]
self._column_refax = [None for _ in range(self._ncols)]
self._row_refax = [None for _ in range(self._nrows)]
self._refax = None

for i in range(self.ngrids):
Expand Down Expand Up @@ -678,7 +705,7 @@ def _update_locators(self):
v_cb_pos = []
for row, ax in enumerate(self.axes_column[0][::-1]):
if v:
v.append(self._horiz_pad_size) # Size.Fixed(self._axes_pad))
v.append(self._vert_pad_size) # Size.Fixed(self._axes_pad))

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

grid = Grid(F, 111, # similar to subplot(111)
nrows_ncols = (2, 2),
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.05,
add_all=True,
Expand All @@ -802,12 +829,12 @@ def _update_locators(self):
F.subplots_adjust(left=0.05, right=0.98)

grid = ImageGrid(F, 131, # similar to subplot(111)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.05,
add_all=True,
label_mode = "1",
)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.05,
add_all=True,
label_mode = "1",
)

Z, extent = get_demo_image()
plt.ioff()
Expand All @@ -821,14 +848,14 @@ def _update_locators(self):
plt.ion()

grid = ImageGrid(F, 132, # similar to subplot(111)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.0,
add_all=True,
share_all=True,
label_mode = "1",
cbar_mode="single",
)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.0,
add_all=True,
share_all=True,
label_mode = "1",
cbar_mode="single",
)

Z, extent = get_demo_image()
plt.ioff()
Expand All @@ -844,17 +871,17 @@ def _update_locators(self):
plt.ion()

grid = ImageGrid(F, 133, # similar to subplot(122)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.1,
add_all=True,
label_mode = "1",
share_all = True,
cbar_location="top",
cbar_mode="each",
cbar_size="7%",
cbar_pad="2%",
)
nrows_ncols=(2, 2),
direction="row",
axes_pad = 0.1,
add_all=True,
label_mode = "1",
share_all = True,
cbar_location="top",
cbar_mode="each",
cbar_size="7%",
cbar_pad="2%",
)
plt.ioff()
for i in range(4):
im = grid[i].imshow(Z, extent=extent, interpolation="nearest")
Expand Down