Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Cleanup Figure methods and subplots.py docs
  • Loading branch information
lukelbd committed Jan 7, 2020
commit 44fb0326689b6037971d9c3ea61fee76890856b3
133 changes: 57 additions & 76 deletions proplot/subplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,6 @@ class Figure(mfigure.Figure):
the space around the figure edge, between subplots, and between
panels is changed to accommodate subplot content. Figure dimensions
may be automatically scaled to preserve subplot aspect ratios."""

def __init__(
self, tight=None,
ref=1, pad=None, axpad=None, panelpad=None, includepanels=False,
Expand Down Expand Up @@ -1027,7 +1026,7 @@ def _add_figure_panel(
self, side, span=None, row=None, col=None, rows=None, cols=None,
**kwargs
):
"""Adds figure panels. Also modifies the panel attribute stored
"""Add a figure panel. Also modifies the panel attribute stored
on the figure to include these panels."""
# Interpret args and enforce sensible keyword args
s = side[0]
Expand Down Expand Up @@ -1127,9 +1126,9 @@ def _add_figure_panel(
return pax

def _adjust_aspect(self):
"""Adjust average aspect ratio used for gridspec calculations. This
fixes grids with identically fixed aspect ratios, e.g. identically
zoomed-in cartopy projections and imshow images."""
"""Adjust the average aspect ratio used for gridspec calculations.
This fixes grids with identically fixed aspect ratios, e.g.
identically zoomed-in cartopy projections and imshow images."""
# Get aspect ratio
if not self._axes_main:
return
Expand Down Expand Up @@ -1159,10 +1158,8 @@ def _adjust_aspect(self):
self._gridspec_main.update(**gridspec_kw)

def _adjust_tight_layout(self, renderer, resize=True):
"""Applies tight layout scaling that permits flexible figure
dimensions and preserves panel widths and subplot aspect ratios.
The `renderer` should be a `~matplotlib.backend_bases.RendererBase`
instance."""
"""Apply tight layout scaling that permits flexible figure
dimensions and preserves panel widths and subplot aspect ratios."""
# Initial stuff
axs = self._iter_axes()
subplots_kw = self._subplots_kw
Expand Down Expand Up @@ -1447,8 +1444,8 @@ def _context_preprocessing(self):
return _setstate(self, _is_preprocessing=True)

def _get_align_coord(self, side, axs):
"""Returns figure coordinate for spanning labels and super title. The
`x` can be ``'x'`` or ``'y'``."""
"""Return the figure coordinate for spanning labels or super titles.
The `x` can be ``'x'`` or ``'y'``."""
# Get position in figure relative coordinates
s = side[0]
x = ('y' if s in 'lr' else 'x')
Expand All @@ -1472,7 +1469,7 @@ def _get_align_coord(self, side, axs):
return pos, spanax

def _get_align_axes(self, side):
"""Returns main axes along the left, right, bottom, or top sides
"""Return the main axes along the left, right, bottom, or top sides
of the figure."""
# Initial stuff
s = side[0]
Expand Down Expand Up @@ -1515,10 +1512,9 @@ def _insert_row_column(
self, side, idx,
ratio, space, space_orig, figure=False,
):
"""Helper function that "overwrites" the main figure gridspec to make
room for a panel. The `side` is the panel side, the `idx` is the
slot you want the panel to occupy, and the remaining args are the
panel widths and spacings."""
""""Overwrite" the main figure gridspec to make room for a panel. The
`side` is the panel side, the `idx` is the slot you want the panel
to occupy, and the remaining args are the panel widths and spacings."""
# Constants and stuff
# Insert spaces to the left of right panels or to the right of
# left panels. And note that since .insert() pushes everything in
Expand Down Expand Up @@ -1616,14 +1612,14 @@ def _insert_row_column(
return gridspec

def _update_figtitle(self, title, **kwargs):
"""Assign figure "super title"."""
"""Assign the figure "super title" and update settings."""
if title is not None and self._suptitle.get_text() != title:
self._suptitle.set_text(title)
if kwargs:
self._suptitle.update(kwargs)

def _update_labels(self, ax, side, labels, **kwargs):
"""Assigns side labels, updates label settings."""
"""Assign the side labels and update settings."""
s = side[0]
if s not in 'lrbt':
raise ValueError(f'Invalid label side {side!r}.')
Expand Down Expand Up @@ -1730,19 +1726,6 @@ def get_aligny(self):
"""Return the *y* axis label alignment mode."""
return self._aligny

def get_gridspec(self):
"""Return the single `GridSpec` instance associated with this figure.
If the `GridSpec` has not yet been initialized, returns ``None``."""
return self._gridspec

def get_ref_axes(self):
"""Return the reference axes associated with the reference axes
number `Figure.ref`."""
for ax in self._mainaxes:
if ax.number == self.ref:
return ax
return None # no error

def get_sharex(self):
"""Return the *x* axis sharing level."""
return self._sharex
Expand Down Expand Up @@ -1834,13 +1817,11 @@ def legend(

def save(self, filename, **kwargs):
# Alias for `~Figure.savefig` because ``fig.savefig`` is redundant.
# Also automatically expands user paths e.g. the tilde ``'~'``.
return self.savefig(filename, **kwargs)

def savefig(self, filename, **kwargs):
# Automatically expand user because why in gods name does
# matplotlib not already do this. Undocumented because do not
# want to overwrite matplotlib docstring.
# Automatically expand user the user name. Undocumented because we
# do not want to overwrite the matplotlib docstring.
super().savefig(os.path.expanduser(filename), **kwargs)

def set_canvas(self, canvas):
Expand All @@ -1859,6 +1840,42 @@ def set_canvas(self, canvas):
canvas.print_figure = _canvas_preprocess(canvas, 'print_figure')
super().set_canvas(canvas)

def set_size_inches(self, w, h=None, forward=True, auto=False):
# Set the figure size and, if this is being called manually or from
# an interactive backend, override the geometry tracker so users can
# use interactive backends. See #76. Undocumented because this is
# only relevant internally.
# NOTE: Bitmap renderers use int(Figure.bbox.[width|height]) which
# rounds to whole pixels. So when renderer resizes the figure
# internally there may be roundoff error! Always compare to *both*
# Figure.get_size_inches() and the truncated bbox dimensions times dpi.
# Comparison is critical because most renderers call set_size_inches()
# before any resizing interaction!
if h is None:
width, height = w
else:
width, height = w, h
if not all(np.isfinite(_) for _ in (width, height)):
raise ValueError(
'Figure size must be finite, not ({width}, {height}).'
)
width_true, height_true = self.get_size_inches()
width_trunc = int(self.bbox.width) / self.dpi
height_trunc = int(self.bbox.height) / self.dpi
if auto:
with self._context_resizing():
super().set_size_inches(width, height, forward=forward)
else:
if ( # can have internal resizing not associated with any draws
(width not in (width_true, width_trunc)
or height not in (height_true, height_trunc))
and not self._is_resizing
and not self.canvas._is_idle_drawing # standard
and not getattr(self.canvas, '_draw_pending', None) # pyqt5
):
self._subplots_kw.update(width=width, height=height)
super().set_size_inches(width, height, forward=forward)

def set_alignx(self, value):
"""Set the *x* axis label alignment mode."""
self.stale = True
Expand Down Expand Up @@ -1928,42 +1945,6 @@ def ref(self, ref):
self.stale = True
self._ref = ref

def set_size_inches(self, w, h=None, forward=True, auto=False):
# Set the figure size and, if this is being called manually or from
# an interactive backend, override the geometry tracker so users can
# use interactive backends. See #76. Undocumented because this is
# only relevant internally.
# NOTE: Bitmap renderers use int(Figure.bbox.[width|height]) which
# rounds to whole pixels. So when renderer resizes the figure
# internally there may be roundoff error! Always compare to *both*
# Figure.get_size_inches() and the truncated bbox dimensions times dpi.
# Comparison is critical because most renderers call set_size_inches()
# before any resizing interaction!
if h is None:
width, height = w
else:
width, height = w, h
if not all(np.isfinite(_) for _ in (width, height)):
raise ValueError(
'Figure size must be finite, not ({width}, {height}).'
)
width_true, height_true = self.get_size_inches()
width_trunc = int(self.bbox.width) / self.dpi
height_trunc = int(self.bbox.height) / self.dpi
if auto:
with self._context_resizing():
super().set_size_inches(width, height, forward=forward)
else:
if ( # can have internal resizing not associated with any draws
(width not in (width_true, width_trunc)
or height not in (height_true, height_trunc))
and not self._is_resizing
and not self.canvas._is_idle_drawing # standard
and not getattr(self.canvas, '_draw_pending', None) # pyqt5
):
self._subplots_kw.update(width=width, height=height)
super().set_size_inches(width, height, forward=forward)

def _iter_axes(self):
"""Iterates over all axes and panels in the figure belonging to the
`~proplot.axes.Axes` class. Excludes inset and twin axes."""
Expand All @@ -1983,7 +1964,7 @@ def _iter_axes(self):


def _journals(journal):
"""Journal sizes for figures."""
"""Return the width and height corresponding to the given journal."""
# Get dimensions for figure from common journals.
value = JOURNAL_SPECS.get(journal, None)
if value is None:
Expand All @@ -2002,7 +1983,7 @@ def _journals(journal):


def _axes_dict(naxs, value, kw=False, default=None):
"""Build a dictionary that looks like ``{1:value1, 2:value2, ...}`` or
"""Return a dictionary that looks like ``{1:value1, 2:value2, ...}`` or
``{1:{key1:value1, ...}, 2:{key2:value2, ...}, ...}`` for storing
standardized axes-specific properties or keyword args."""
# First build up dictionary
Expand Down Expand Up @@ -2063,9 +2044,9 @@ def subplots(
**kwargs
):
"""
Create a figure with a single axes or arbitrary grid of axes, analogous
to `matplotlib.pyplot.subplots`. The axes can have arbitrary map
projections.
Create a figure with a single subplot or arbitrary grids of subplots,
analogous to `matplotlib.pyplot.subplots`. The subplots can be drawn with
arbitrary projections.

Parameters
----------
Expand Down