def make_square_axes_with_colorbar(ax, size=0.1, pad=0.1): """ Make an axes square, add a colorbar axes next to it, Parameters: size: Size of colorbar axes in inches pad : Padding between axes and cbar in inches Returns: colorbar axes """ divider = make_axes_locatable(ax) margin_size = axes_size.Fixed(size) pad_size = axes_size.Fixed(pad) xsizes = [pad_size, margin_size] yhax = divider.append_axes( "right", size=margin_size, pad=pad_size) divider.set_horizontal( [RemainderFixed(xsizes, [], divider)] + xsizes) divider.set_vertical([RemainderFixed(xsizes, [], divider)]) return yhax
def test_hbox_divider(): arr1 = np.arange(20).reshape((4, 5)) arr2 = np.arange(20).reshape((5, 4)) fig, (ax1, ax2) = plt.subplots(1, 2) ax1.imshow(arr1) ax2.imshow(arr2) pad = 0.5 # inches. divider = HBoxDivider( fig, 111, # Position of combined axes. horizontal=[Size.AxesX(ax1), Size.Fixed(pad), Size.AxesX(ax2)], vertical=[Size.AxesY(ax1), Size.Scaled(1), Size.AxesY(ax2)]) ax1.set_axes_locator(divider.new_locator(0)) ax2.set_axes_locator(divider.new_locator(2)) fig.canvas.draw() p1 = ax1.get_position() p2 = ax2.get_position() assert p1.height == p2.height assert p2.width / p1.width == pytest.approx((4 / 5)**2)
def make_heights_equal(fig, rect, ax1, ax2, pad): # pad in inches h1, v1 = Size.AxesX(ax1), Size.AxesY(ax1) h2, v2 = Size.AxesX(ax2), Size.AxesY(ax2) pad_v = Size.Scaled(1) pad_h = Size.Fixed(pad)
def make_square_add_cbar(ax, size=.4, pad=0.1): """ Make input axes square and return an appended axes to the right for a colorbar. Both axes resize together to fit figure automatically. Works with tight_layout(). """ divider = make_axes_locatable(ax) margin_size = axes_size.Fixed(size) pad_size = axes_size.Fixed(pad) xsizes = [pad_size, margin_size] ysizes = xsizes cax = divider.append_axes("right", size=margin_size, pad=pad_size) divider.set_horizontal([RemainderFixed(xsizes, ysizes, divider)] + xsizes) divider.set_vertical([RemainderFixed(xsizes, ysizes, divider)] + ysizes) return cax
def append_axes(ax, size=0.1, pad=0.1, position="right"): """ Append a side ax to the current figure and return it. Figure is automatically extended along the direction of the added axes to accommodate it. Unfortunately can not be reliably chained. """ fig = ax.figure bbox = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) width, height = bbox.width, bbox.height def convert(fraction, position=position): if isinstance(fraction, str): if fraction.endswith("%"): if position in ['right', 'left']: fraction = width * float(fraction.strip('%')) / 100 elif position in ['top', 'bottom']: fraction = height * float(fraction.strip('%')) / 100 return fraction size = convert(size) pad = convert(pad) divider = make_axes_locatable(ax) margin_size = axes_size.Fixed(size) pad_size = axes_size.Fixed(pad) xsizes = [pad_size, margin_size] if position in ['top', 'bottom']: xsizes = xsizes[::-1] yhax = divider.append_axes(position, size=margin_size, pad=pad_size) def extend_ratio(ax): ax.figure.canvas.draw() orig_size = ax.get_position().size new_size = 0 for itax in ax.figure.axes: new_size += itax.get_position().size return new_size / orig_size if position in ["right"]: divider.set_horizontal([axes_size.Fixed(width)] + xsizes) fig.set_size_inches(fig.get_size_inches()[0] * extend_ratio(ax)[0], fig.get_size_inches()[1]) elif position in ["left"]: divider.set_horizontal(xsizes[::-1] + [axes_size.Fixed(width)]) fig.set_size_inches(fig.get_size_inches()[0] * extend_ratio(ax)[0], fig.get_size_inches()[1]) elif position in ['top']: divider.set_vertical([axes_size.Fixed(height)] + xsizes[::-1]) fig.set_size_inches(fig.get_size_inches()[0], fig.get_size_inches()[1] * extend_ratio(ax)[1]) ax.get_shared_x_axes().join(ax, yhax) elif position in ['bottom']: divider.set_vertical(xsizes + [axes_size.Fixed(height)]) fig.set_size_inches(fig.get_size_inches()[0], fig.get_size_inches()[1] * extend_ratio(ax)[1]) ax.get_shared_x_axes().join(ax, yhax) return yhax
def make_heights_equal(fig, rect, ax1, ax2, pad): # pad in inches divider = HBoxDivider( fig, rect, horizontal=[Size.AxesX(ax1), Size.Fixed(pad), Size.AxesX(ax2)], vertical=[Size.AxesY(ax1), Size.Scaled(1), Size.AxesY(ax2)]) ax1.set_axes_locator(divider.new_locator(0)) ax2.set_axes_locator(divider.new_locator(2))
def make_heights_equal(fig, rect, ax1, ax2, pad): # pad in inches h1, v1 = Size.AxesX(ax1), Size.AxesY(ax1) h2, v2 = Size.AxesX(ax2), Size.AxesY(ax2) pad_v = Size.Scaled(1) pad_h = Size.Fixed(pad) my_divider = HBoxDivider(fig, rect, horizontal=[h1, pad_h, h2], vertical=[v1, pad_v, v2]) ax1.set_axes_locator(my_divider.new_locator(0)) ax2.set_axes_locator(my_divider.new_locator(2))
def subplot_array(self, hsize, vsize=(1.0, ), figsize=(10, 10)): """ Use the axes_divider module to make a single row of plots hsize : list of floats horizontal spacing: alternates Scaled for plot, Fixed for between plots vsize : list of floats vertical spacing ref: http://matplotlib.org/mpl_toolkits/axes_grid/users/axes_divider.html """ nx = (len(hsize) + 1) / 2 ny = (len(vsize) + 1) / 2 fig, axx = plt.subplots( ny, nx, squeeze=False, figsize=figsize) # just to make the axes, will move them sizer = lambda x, i: axes_size.Scaled( x) if i % 2 == 0 else axes_size.Fixed(x) horiz = [sizer(h, i) for i, h in enumerate(hsize)] vert = [sizer(v, i) for i, v in enumerate(vsize)] divider = Divider(fig, (0.1, 0.1, 0.8, 0.8), horiz, vert, aspect=False) for i, ax in enumerate(axx.flatten()): iy = i // nx ix = i % nx ax.set_axes_locator(divider.new_locator(nx=2 * ix, ny=2 * iy)) return fig, axx
import mpl_toolkits.axes_grid1.axes_size as Size from mpl_toolkits.axes_grid1 import Divider import matplotlib.pyplot as plt fig = plt.figure(figsize=(5.5, 4)) rect = (0.1, 0.1, 0.8, 0.8) ax = [fig.add_axes(rect, label="%d" % i) for i in range(4)] horiz = [Size.AxesX(ax[0]), Size.Fixed(.5), Size.AxesX(ax[1])] vert = [Size.AxesY(ax[0]), Size.Fixed(.5), Size.AxesY(ax[2])] divider = Divider(fig, rect, horiz, vert, aspect=False) ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0)) ax[1].set_axes_locator(divider.new_locator(nx=2, ny=0)) ax[2].set_axes_locator(divider.new_locator(nx=0, ny=2)) ax[3].set_axes_locator(divider.new_locator(nx=2, ny=2)) ax[0].set_xlim(0, 2) ax[1].set_xlim(0, 1) ax[0].set_ylim(0, 1) ax[2].set_ylim(0, 2) divider.set_aspect(1.) for ax1 in ax: ax1.tick_params(labelbottom=False, labelleft=False) plt.show()
===================== Simple Axes Divider 2 ===================== """ import mpl_toolkits.axes_grid1.axes_size as Size from mpl_toolkits.axes_grid1 import Divider import matplotlib.pyplot as plt fig1 = plt.figure(1, (5.5, 4.)) # the rect parameter will be ignore as we will set axes_locator rect = (0.1, 0.1, 0.8, 0.8) ax = [fig1.add_axes(rect, label="%d" % i) for i in range(4)] horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.), Size.Scaled(.5)] vert = [Size.Scaled(1.), Size.Fixed(.5), Size.Scaled(1.5)] # divide the axes rectangle into grid whose size is specified by horiz * vert divider = Divider(fig1, rect, horiz, vert, aspect=False) ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0)) ax[1].set_axes_locator(divider.new_locator(nx=0, ny=2)) ax[2].set_axes_locator(divider.new_locator(nx=2, ny=2)) ax[3].set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0)) for ax1 in ax: plt.setp(ax1.get_xticklabels() + ax1.get_yticklabels(), visible=False) plt.draw()
def init_plot(): dpi = 100 # class matplotlib.figure.Figure(figsize=None, # dpi=None, facecolor=None, # edgecolor=None, linewidth=1.0, # frameon=True, subplotpars=None) fig = Figure(figsize=(3.0, 3.0), dpi=dpi) canvas = FigCanvas(fig) canvas.add_events(Gdk.EventMask.SCROLL_MASK) rect = [.1, .01, .88, .85] horiz = [Size.Scaled(1.0)] vert = [ Size.Fixed(0.23), Size.Fixed(.25), Size.Scaled(1.), Size.Fixed(.1), Size.Scaled(1.0) ] divider = Divider(fig, rect, horiz, vert, aspect=False) axes = dict() # ##### ANALOG AXES ##### # The args to add_subplot seem to be # # of rows # # of columns # # pos of this plot in row order axes['analog'] = fig.add_axes(rect, label='analog', navigate=True) axes['analog'].set_axes_locator(divider.new_locator(nx=0, ny=4)) #axes['analog'].set_axis_bgcolor('black') axes['analog'].set_ylabel('Output (V)') #axes['analog'].xaxis.set_label_position('top') axes['analog'].xaxis.set_ticks_position('top') #axes['analog'].set_xlabel('Time (s)') # ##### DIGITAL AXES ##### axes['digital'] = fig.add_axes(rect, label='digital', navigate=True, sharex=axes['analog']) axes['digital'].set_axes_locator(divider.new_locator(nx=0, ny=2)) #axes['digital'].xaxis.set_ticks_position('top') # ##### SCROLL INDICATOR AXES ##### axes['t'] = fig.add_axes(rect, label='time') axes['t'].set_axes_locator(divider.new_locator(nx=0, ny=0)) axes['t'].set_yticks(()) #axes['t'].set_xlabel('Time (s)') axes['t'].set_xticklabels(()) # set up GUI interactions and widgets axes['multi'] = MultiCursor( canvas, (axes['analog'], axes['digital'], axes['t']), color='r', lw=1, useblit=True, ) axes['__scroll_master'] = ScrollMaster(axes['analog'], axes['digital'], axes['t']) axes['hspan-controls'] = dict() axes['vspan-controls'] = dict() # set useblit True on gtk3agg for enhanced performance axes['hspan-controls']['analog'] = SpanSelector( axes['analog'], axes['__scroll_master'].onselect_horizontal, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='green'), ) setattr(axes['hspan-controls']['analog'], 'visible', False) axes['vspan-controls']['analog'] = SpanSelector( axes['analog'], axes['__scroll_master'].onselect_vertical1, 'vertical', useblit=True, rectprops=dict(alpha=0.5, facecolor='green'), ) setattr(axes['vspan-controls']['analog'], 'visible', False) # set useblit True on gtk3agg for enhanced performance axes['hspan-controls']['digital'] = SpanSelector( axes['digital'], axes['__scroll_master'].onselect_horizontal, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='green'), ) setattr(axes['hspan-controls']['digital'], 'visible', False) axes['vspan-controls']['digital'] = SpanSelector( axes['digital'], axes['__scroll_master'].onselect_vertical2, 'vertical', useblit=True, rectprops=dict(alpha=0.5, facecolor='green'), ) setattr(axes['vspan-controls']['digital'], 'visible', False) # set useblit True on gtk3agg for enhanced performance axes['hspan-controls']['t'] = SpanSelector( axes['t'], axes['__scroll_master'].onselect_horizontal, 'horizontal', useblit=False, rectprops=dict(alpha=0.5, facecolor='red'), ) setattr(axes['hspan-controls']['t'], 'visible', False) canvas.mpl_connect('scroll_event', axes['__scroll_master'].onscroll) #canvas.connect('key-press-event', axes['__scroll_master'].onpress) zoom_effect(axes['digital'], axes['t']) # plot the data as a line series, and save the reference # to the plotted line series # #self.vector = [0] #self.plot_data = axes.plot( # self.vector, # linewidth=4, # color=(1, 1, 0), # marker='o', # label="set1", # )[0] #self.vector2 = [0] #self.plot_data2 = axes.plot( # self.vector2, # linewidth=2, # dashes=[.2,.4], # color=(0, 0, 1), # label="set2", # )[0] # leg = axes.legend() # # the matplotlib.patches.Rectangle instance surrounding the legend # frame = leg.get_frame() # frame.set_facecolor('0.80') # set the frame face color to light gray return axes, fig, canvas
def _setup_image_grid(self, figure, dims): """ An example of how grid, parameter and view numbers change for dims = 4 The numbers in the grid are: parameter x, parameter y grid x, grid y ----------------------------------------------------- | | | | | | 0, 0 | 1, 0 | 2, 0 | 3, 0 | | -, - | -, - | -, - | -, - | | | | | | ==============------------|------------|------------| I I | | | I 0, 1 I 1, 1 | 2, 1 | 3, 1 | I 0, 0 I 1, 0 | 2, 0 | -, - | I I | | | I------------==============------------|------------| I | I | | I 0, 2 | 1, 2 I 2, 2 | 3, 2 | I 0, 1 | 1, 1 I 2, 1 | -, - | I | I | | I------------|------------==============------------| I | | I | I 0, 3 | 1, 3 | 2, 3 I 3, 3 | I 0, 2 | 1, 2 | 2, 2 I -, - | I | | I | I======================================I------------| From the above it should be clear that: parameter x = grid x parameter y = grid y + 1 grid nr = grid y + grid x * (dims - 1) view nr = grid nr - (grid nr / dims) * ((grid nr / dims) +1) / 2 """ image_grid = ImageGrid( figure, 111, nrows_ncols=(dims - 1, dims - 1), cbar_location="right", cbar_mode="single", # add_all=False, aspect=False, axes_pad=0.1, direction="column") rect = (0.1, 0.1, 0.8, 0.8) horiz = [Size.Fixed(.1) ] + [Size.Scaled(1.), Size.Fixed(.1)] * max(dims - 1, 1) + [ Size.Fixed(0.15) ] vert = [Size.Fixed(.1) ] + [Size.Scaled(1.), Size.Fixed(.1)] * max(dims - 1, 1) # divide the axes rectangle into grid whose size is specified by horiz * vert divider = Divider(figure, rect, horiz, vert) # , aspect=False) # Helper to get the axis for par x and y: def get_grid(parx, pary): gridx = parx gridy = pary - 1 return image_grid[gridy + gridx * (dims - 1)] # Helper to get the grid locator for par x and par y def get_locator(parx, pary): gridx = parx gridy = pary - 1 nx = 1 + gridx * 2 ny = 1 + (dims - gridy - 2) * 2 return divider.new_locator(nx=nx, ny=ny) # Hide the unused plots & setup the used ones: for parx, pary in itertools.product(list(range(self.num_params - 1)), list(range(1, self.num_params))): # Calculate the grid position: ax = get_grid(parx, pary) # Setup axes: if pary <= parx: ax.set_visible(False) else: ax.set_axes_locator(get_locator(parx, pary)) ax.set_visible(True) return image_grid, divider, get_grid
if __name__ == "__main__": arr1 = np.arange(20).reshape((4, 5)) arr2 = np.arange(20).reshape((5, 4)) fig, (ax1, ax2) = plt.subplots(1, 2) ax1.imshow(arr1) ax2.imshow(arr2) pad = 0.5 # inches. divider = HBoxDivider( fig, 111, # Position of combined axes. horizontal=[Size.AxesX(ax1), Size.Fixed(pad), Size.AxesX(ax2)], vertical=[Size.AxesY(ax1), Size.Scaled(1), Size.AxesY(ax2)]) ax1.set_axes_locator(divider.new_locator(0)) ax2.set_axes_locator(divider.new_locator(2)) # annotate ax3 = plt.axes([0.5, 0.5, 0.001, 0.001], frameon=False) ax3.xaxis.set_visible(False) ax3.yaxis.set_visible(False) ax3.annotate( "Location of two axes are adjusted\n" "so that they have equal heights\n" "while maintaining their aspect ratios", (0.5, 0.5),