Skip to content

Commit c4a3bab

Browse files
committed
Improve default right/bottom colorbar spaces
1 parent 4037e70 commit c4a3bab

1 file changed

Lines changed: 56 additions & 38 deletions

File tree

proplot/gridspec.py

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,13 @@ def __init__(self, nrows=1, ncols=1, **kwargs):
254254
# Capture rc settings used for default spacing
255255
# NOTE: This is consistent with conversion of 'em' units to inches on gridspec
256256
# instantiation. In general it seems strange for future changes to rc settings
257-
# to magically update an existing gridspec layout. This also may improve
258-
# lookup time since get_grid_positions() is called heaviliy.
257+
# to magically update an existing gridspec layout. This also may improve draw
258+
# time as manual or auto figure resizes repeatedly call get_grid_positions().
259259
scales = {'in': 0, 'inout': 0.5, 'out': 1, None: 1}
260260
self._xtickspace = scales[rc['xtick.direction']] * rc['xtick.major.size']
261261
self._ytickspace = scales[rc['ytick.direction']] * rc['ytick.major.size']
262262
self._xticklabelspace = _fontsize_to_pt(rc['xtick.labelsize']) + rc['xtick.major.pad'] # noqa: E501
263-
self._yticklabelspace = 3 * _fontsize_to_pt(rc['ytick.labelsize']) + rc['ytick.major.pad'] # noqa: E501
263+
self._yticklabelspace = 2 * _fontsize_to_pt(rc['ytick.labelsize']) + rc['ytick.major.pad'] # noqa: E501
264264
self._labelspace = _fontsize_to_pt(rc['axes.labelsize']) + rc['axes.labelpad']
265265
self._titlespace = _fontsize_to_pt(rc['axes.titlesize']) + rc['axes.titlepad']
266266

@@ -507,9 +507,6 @@ def _insert_panel_slot(
507507
and the `arg` is either an axes instance or the figure row-column span.
508508
"""
509509
# Parse input args and get user-input properties, default properties
510-
# NOTE: This gives totally wrong space for 'right' and 'top' colorbars with
511-
# tick locations on the outside but that's ok... otherwise would have to
512-
# modify existing space which is overkill. People should use tight layout
513510
fig = self.figure
514511
if fig is None:
515512
raise RuntimeError('Figure must be assigned to gridspec.')
@@ -519,63 +516,84 @@ def _insert_panel_slot(
519516
pad = units(pad, 'em', 'in')
520517
space = units(space, 'em', 'in')
521518
width = units(width, 'in')
522-
share = False if filled else _not_none(share, True)
519+
share = False if filled else share if share is not None else True
523520
which = 'w' if side in ('left', 'right') else 'h'
524521
panels = getattr(self, f'_{which}panels')
525522
pads = getattr(self, f'_{which}pad_total') # no copies!
526523
ratios = getattr(self, f'_{which}ratios_total')
527524
spaces = getattr(self, f'_{which}space_total')
528525
spaces_default = getattr(self, f'_{which}space_total_default')
526+
new_outer_slot = idx in (-1, len(panels))
527+
new_inner_slot = not new_outer_slot and panels[idx] != slot
528+
529+
# Retrieve default spaces
530+
# NOTE: Cannot use 'wspace' and 'hspace' for top and right colorbars because
531+
# that adds an unnecessary tick space. So bypass _get_default_space totally.
529532
pad_default = (
530533
self._panelpad
531534
if slot != 'f'
532535
or side in ('left', 'top') and panels[0] == 'f'
533536
or side in ('right', 'bottom') and panels[-1] == 'f'
534537
else self._innerpad
535538
)
536-
space_default = (
539+
inner_space_default = (
537540
_not_none(pad, pad_default)
538541
if side in ('top', 'right')
539542
else self._get_default_space(
540543
'hspace_total' if side == 'bottom' else 'wspace_total',
541-
title=False, # no title space
542-
share=3 if share else 0,
544+
title=False, # no title between subplot and panel
545+
share=3 if share else 0, # space for main subplot labels
543546
pad=_not_none(pad, pad_default),
544547
)
545548
)
549+
outer_space_default = self._get_default_space(
550+
'bottom' if not share and side == 'top'
551+
else 'left' if not share and side == 'right'
552+
else side,
553+
title=True, # room for titles deflected above panels
554+
pad=self._outerpad if new_outer_slot else self._innerpad,
555+
)
556+
if new_inner_slot:
557+
outer_space_default += self._get_default_space(
558+
'hspace_total' if side in ('bottom', 'top') else 'wspace_total',
559+
share=None, # use external share setting
560+
pad=0, # use no additional padding
561+
)
546562
width_default = units(
547563
rc['colorbar.width' if filled else 'subplots.panelwidth'], 'in'
548564
)
549565

550566
# Adjust space, ratio, and panel indicator arrays
551567
# If slot exists, overwrite width, pad, space if they were provided by the user
552568
# If slot does not exist, modify gemoetry and add insert new spaces
553-
newrow = newcol = None
554-
idx_off = 1 * bool(side in ('top', 'left'))
555-
idx_space = idx - 1 * bool(side in ('bottom', 'right'))
556-
slot_exists = idx not in (-1, len(panels)) and panels[idx] == slot
557-
if slot_exists:
558-
spaces_default[idx_space] = space_default
569+
attr = 'ncols' if side in ('left', 'right') else 'nrows'
570+
idx_offset = int(side in ('top', 'left'))
571+
idx_inner_space = idx - int(side in ('bottom', 'right')) # inner colorbar space
572+
idx_outer_space = idx - int(side in ('top', 'left')) # outer colorbar space
573+
if new_outer_slot or new_inner_slot:
574+
idx += idx_offset
575+
idx_inner_space += idx_offset
576+
idx_outer_space += idx_offset
577+
newcol, newrow = (idx, None) if attr == 'ncols' else (None, idx)
578+
setattr(self, f'_{attr}_total', 1 + getattr(self, f'_{attr}_total'))
579+
panels.insert(idx, slot)
580+
ratios.insert(idx, _not_none(width, width_default))
581+
pads.insert(idx_inner_space, _not_none(pad, pad_default))
582+
spaces.insert(idx_inner_space, space)
583+
spaces_default.insert(idx_inner_space, inner_space_default)
584+
if new_inner_slot:
585+
spaces_default.insert(idx_outer_space, outer_space_default)
586+
else:
587+
setattr(self, f'_{side}_default', outer_space_default)
588+
else:
589+
newrow = newcol = None
590+
spaces_default[idx_inner_space] = inner_space_default
559591
if width is not None:
560592
ratios[idx] = width
561593
if pad is not None:
562-
pads[idx_space] = pad
594+
pads[idx_inner_space] = pad
563595
if space is not None:
564-
spaces[idx_space] = space
565-
else:
566-
idx += idx_off
567-
idx_space += idx_off
568-
if side in ('left', 'right'):
569-
newcol = idx
570-
self._ncols_total += 1
571-
else:
572-
newrow = idx
573-
self._nrows_total += 1
574-
panels.insert(idx, slot)
575-
ratios.insert(idx, _not_none(width, width_default))
576-
pads.insert(idx_space, _not_none(pad, pad_default))
577-
spaces.insert(idx_space, space)
578-
spaces_default.insert(idx_space, space_default)
596+
spaces[idx_inner_space] = space
579597

580598
# Update the figure and axes and return a SubplotSpec
581599
# NOTE: For figure panels indices are determined by user-input spans.
@@ -591,8 +609,8 @@ def _insert_panel_slot(
591609

592610
def _get_space(self, key):
593611
"""
594-
Get the currently active space accounting for both default
595-
values and explicit user-specified values.
612+
Return the currently active vector inner space or scalar outer space
613+
accounting for both default values and explicit user overrides.
596614
"""
597615
# NOTE: Default panel spaces should have been filled by _insert_panel_slot.
598616
# They use 'panelpad' and the panel-local 'share' setting. This function
@@ -622,8 +640,8 @@ def _get_space(self, key):
622640

623641
def _get_default_space(self, key, pad=None, share=None, title=True):
624642
"""
625-
Return suitable default spacing given a shared axes setting.
626-
This is only relevant when "tight layout" is disabled.
643+
Return suitable default scalar inner or outer space given a shared axes
644+
setting. This is only relevant when "tight layout" is disabled.
627645
"""
628646
# NOTE: Internal spacing args are stored in inches to simplify the
629647
# get_grid_positions() calculations.
@@ -642,15 +660,15 @@ def _get_default_space(self, key, pad=None, share=None, title=True):
642660
elif key == 'bottom':
643661
pad = _not_none(pad, self._outerpad)
644662
space = self._labelspace + self._xticklabelspace + self._xtickspace
645-
elif key in ('wspace', 'wspace_total'):
663+
elif key == 'wspace_total':
646664
pad = _not_none(pad, self._innerpad)
647665
share = _not_none(share, fig._sharey, 0)
648666
space = self._ytickspace
649667
if share < 3:
650668
space += self._yticklabelspace
651669
if share < 1:
652670
space += self._labelspace
653-
elif key in ('hspace', 'hspace_total'):
671+
elif key == 'hspace_total':
654672
pad = _not_none(pad, self._innerpad)
655673
share = _not_none(share, fig._sharex, 0)
656674
space = self._xtickspace

0 commit comments

Comments
 (0)