Skip to content

Commit

Permalink
More improvements to clustergrid layout
Browse files Browse the repository at this point in the history
This enables use of tight_layout within clustermap. Ideally most plots will
now have everything in the figure and looking nice out of the box. It uses
a somewhat hacky approach that should be revisted as constrained_layout matures.

Also updates the docs a little bit and adds a rule where cbar_pos=None implies
that no colorbar will be drawn.
  • Loading branch information
mwaskom committed Jan 21, 2020
1 parent 5c4562d commit 4739e2e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
39 changes: 31 additions & 8 deletions seaborn/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,8 @@ def heatmap(data, vmin=None, vmax=None, cmap=None, center=None, robust=False,
Axes in which to draw the plot, otherwise use the currently-active
Axes.
kwargs : other keyword arguments
All other keyword arguments are passed to ``ax.pcolormesh``.
All other keyword arguments are passed to
:func:`matplotlib.axes.Axes.pcolormesh`.
Returns
-------
Expand Down Expand Up @@ -796,8 +797,9 @@ def __init__(self, data, pivot_kws=None, z_score=None, standard_scale=None,
nrows = 2 if self.col_colors is None else 3
ncols = 2 if self.row_colors is None else 3

self.gs = gridspec.GridSpec(nrows, ncols, wspace=.01, hspace=.01,
left=.01, right=.99, bottom=.01, top=.99,
self.gs = gridspec.GridSpec(nrows, ncols,
# wspace=.01, hspace=.01,
# left=.01, right=.99, bottom=.01, top=.99,
width_ratios=width_ratios,
height_ratios=height_ratios)

Expand All @@ -817,8 +819,14 @@ def __init__(self, data, pivot_kws=None, z_score=None, standard_scale=None,
self.gs[1, -1])

self.ax_heatmap = self.fig.add_subplot(self.gs[-1, -1])
self.ax_cbar = self.fig.add_axes(cbar_pos)
self.cax = self.ax_cbar # Backwards compatability
if cbar_pos is None:
self.ax_cbar = self.cax = None
else:
# Initialize the colorbar axes in the gridspec so that tight_layout
# works. We will move it where it belongs later. This is a hack.
self.ax_cbar = self.fig.add_subplot(self.gs[0, 0])
self.cax = self.ax_cbar # Backwards compatability
self.cbar_pos = cbar_pos

self.dendrogram_row = None
self.dendrogram_col = None
Expand Down Expand Up @@ -1136,6 +1144,8 @@ def plot_matrix(self, colorbar_kws, xind, yind, **kws):
annot_data = annot_data[yind][:, xind]
annot = annot_data

# Setting ax_cbar=None in clustermap call implies no colorbar
kws.setdefault("cbar", self.ax_cbar is not None)
heatmap(self.data2d, ax=self.ax_heatmap, cbar_ax=self.ax_cbar,
cbar_kws=colorbar_kws, mask=self.mask,
xticklabels=xtl, yticklabels=ytl, annot=annot, **kws)
Expand All @@ -1148,6 +1158,18 @@ def plot_matrix(self, colorbar_kws, xind, yind, **kws):
ytl = self.ax_heatmap.get_yticklabels()
plt.setp(ytl, rotation=ytl_rot)

tight_params = dict(h_pad=.02, w_pad=.02)
if self.ax_cbar is None:
self.fig.tight_layout(**tight_params)
else:
# Turn the colorbar axes off for tight layout so that its
# ticks don't interfere with the rest of the plot layout.
# Then move it.
self.ax_cbar.set_axis_off()
self.fig.tight_layout(**tight_params)
self.ax_cbar.set_axis_on()
self.ax_cbar.set_position(self.cbar_pos)

def plot(self, metric, method, colorbar_kws, row_cluster, col_cluster,
row_linkage, col_linkage, tree_kws, **kws):

Expand Down Expand Up @@ -1241,10 +1263,11 @@ def clustermap(data, pivot_kws=None, method='average', metric='euclidean',
Proportion of the figure size devoted to the two marginal elements. If
a pair is given, they correspond to (row, col) ratios.
cbar_pos : (left, bottom, width, height), optional
Position of the colorbar axes in the figure.
Position of the colorbar axes in the figure. Setting to ``None`` will
disable the colorbar.
tree_kws : dict, optional
Keyword arguments for the ``matplotlib.collections.LineCollection``
that is used for plotting the lines of the dendrogram tree.
Parameters for the :class:`matplotlib.collections.LineCollection`
that is used to plot the lines of the dendrogram tree.
kwargs : other keyword arguments
All other keyword arguments are passed to :func:`heatmap`
Expand Down
4 changes: 4 additions & 0 deletions seaborn/tests/test_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,10 @@ def test_cbar_pos(self):
assert pytest.approx(pos.width) == kws["cbar_pos"][2]
assert pytest.approx(pos.height) == kws["cbar_pos"][3]

kws["cbar_pos"] = None
g = mat.clustermap(self.df_norm, **kws)
assert g.ax_cbar is None

def test_square_warning(self):

kws = self.default_kws.copy()
Expand Down

0 comments on commit 4739e2e

Please sign in to comment.