From f9546ca9ba9c3df38d8d37152fbead27246bfb28 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 10 Sep 2015 21:50:58 +0200 Subject: [PATCH] Use an event-based approach to keeping axes margins fixed to make sure AxesCache works --- glue/clients/histogram_client.py | 8 ++--- glue/clients/viz_client.py | 17 +++++----- glue/utils/matplotlib.py | 57 +++++++++++++++----------------- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/glue/clients/histogram_client.py b/glue/clients/histogram_client.py index b06a53da0..eb1c9ade2 100644 --- a/glue/clients/histogram_client.py +++ b/glue/clients/histogram_client.py @@ -1,7 +1,6 @@ from __future__ import absolute_import, division, print_function import numpy as np -import matplotlib.pyplot as plt from ..core.client import Client from ..core import message as msg @@ -13,7 +12,7 @@ from .util import update_ticks, visible_limits from ..core.callback_property import CallbackProperty, add_callback from ..utils import lookup_class -from ..utils.matplotlib import fixed_margin_axes +from ..utils.matplotlib import fix_margins class UpdateProperty(CallbackProperty): @@ -59,9 +58,8 @@ def __init__(self, data, figure, artist_container=None): super(HistogramClient, self).__init__(data) self._artists = artist_container or LayerArtistContainer() - FixedMarginAxes = fixed_margin_axes(plt.Axes, [1, 0.5, 0.75, 0.5]) - self._axes = FixedMarginAxes(figure) - figure.add_axes(self._axes) + self._axes = figure.add_subplot(111) + fix_margins(self._axes, [1, 0.25, 0.50, 0.25]) self._component = None self._saved_nbins = None self._xlim = {} diff --git a/glue/clients/viz_client.py b/glue/clients/viz_client.py index 9256d0183..b3dff4de7 100644 --- a/glue/clients/viz_client.py +++ b/glue/clients/viz_client.py @@ -3,7 +3,7 @@ import matplotlib.pyplot as plt from ..core.client import Client from ..core import Data -from ..utils.matplotlib import fixed_margin_axes +from ..utils.matplotlib import fix_margins from .layer_artist import LayerArtistContainer __all__ = ['VizClient', 'GenericMplClient'] @@ -143,26 +143,25 @@ def init_mpl(figure, axes, wcs=False, axes_factory=None): raise ValueError("Axes and figure are incompatible") try: - from ..external.wcsaxes import WCSAxes + from ..external.wcsaxes import WCSAxesSubplot except ImportError: - WCSAxes = None + WCSAxesSubplot = None if axes is not None: _axes = axes _figure = axes.figure else: _figure = figure or plt.figure() - if wcs and WCSAxes is not None: - FixedMarginWCSAxes = fixed_margin_axes(WCSAxes, [1, 0.5, 0.75, 0.5]) - _axes = FixedMarginWCSAxes(_figure) + if wcs and WCSAxesSubplot is not None: + _axes = WCSAxesSubplot(_figure, 111) _figure.add_axes(_axes) + fix_margins(_axes, [1, 0.25, 0.50, 0.25]) else: if axes_factory is not None: _axes = axes_factory(_figure) else: - FixedMarginAxes = fixed_margin_axes(plt.Axes, [1, 0.5, 0.75, 0.5]) - _axes = FixedMarginAxes(_figure) - _figure.add_axes(_axes) + _axes = _figure.add_subplot(111) + fix_margins(_axes, [1, 0.25, 0.50, 0.25]) return _figure, _axes diff --git a/glue/utils/matplotlib.py b/glue/utils/matplotlib.py index 9f7f2b1b3..04d0b9ed8 100644 --- a/glue/utils/matplotlib.py +++ b/glue/utils/matplotlib.py @@ -178,47 +178,42 @@ def point_contour(x, y, data): return xy -def fixed_margin_axes(ax_class, margins=[1, 1, 1, 1]): - """ - Class factory to make an axes class that will preserve fixed margins when - figure is resized. +class AxesResizer(object): - Parameters - ---------- - ax_class : matplotlib.axes.Axes - The axes class to wrap - margins : iterable - The margins, in inches. The order of the margins is - ``[left, right, bottom, top]`` - """ + def __init__(self, ax, margins): - # Note that margins gets used directly in get_fixed_margin_rect and we - # don't pass it through the axes class. + self.ax = ax + self.margins = margins - def get_fixed_margin_rect(fig): + def on_resize(self, event): - fig_width = fig.get_figwidth() - fig_height = fig.get_figheight() + fig_width = self.ax.figure.get_figwidth() + fig_height = self.ax.figure.get_figheight() - x0 = margins[0] / fig_width - x1 = 1 - margins[1] / fig_width - y0 = margins[2] / fig_height - y1 = 1 - margins[3] / fig_height + x0 = self.margins[0] / fig_width + x1 = 1 - self.margins[1] / fig_width + y0 = self.margins[2] / fig_height + y1 = 1 - self.margins[3] / fig_height dx = max(0.01, x1 - x0) dy = max(0.01, y1 - y0) - return [x0, y0, dx, dy] + self.ax.set_position([x0, y0, dx, dy]) + self.ax.figure.canvas.draw() - class ax_subclass(ax_class): - def __init__(self, fig, **kwargs): - rect = get_fixed_margin_rect(fig) - super(ax_subclass, self).__init__(fig, rect, **kwargs) +def fix_margins(axes, margins=[1, 1, 1, 1]): + """ + Make sure margins of axes stay fixed. - def draw(self, *args, **kwargs): - rect = get_fixed_margin_rect(self.figure) - self.set_position(rect) - super(ax_subclass, self).draw(*args, **kwargs) + Parameters + ---------- + ax_class : matplotlib.axes.Axes + The axes class for which to fix the margins + margins : iterable + The margins, in inches. The order of the margins is + ``[left, right, bottom, top]`` + """ - return ax_subclass + resizer = AxesResizer(axes, margins) + axes.figure.canvas.mpl_connect('resize_event', resizer.on_resize)