Thursday, 15 May 2014

python - matplotlib: subplot background (axes face + labels) colour [or, figure/axes coordinate systems] -



python - matplotlib: subplot background (axes face + labels) colour [or, figure/axes coordinate systems] -

i have figure containing 3x2 subplots, , set background colour on middle pair of subplots create clearer axis labels belong subplot.

setting facecolor when constructing subplot changes colour of area defined axes; tick , axis labels still drawn on figure.patch. assuming there no simple way this, add together rectangular patch behind relevant instances in figure.axes.

after bit of experimenting around, appears figure.axes[x].get_position() returns axes coördinates (normalised coördinates [0.0-1.0]), yet rectangle() appears want display coördinates (pixels). code more or less works (ed: interactively, when outputting png (using agg renderer), positioning of rectangle off):

import matplotlib.pyplot plt import matplotlib f = plt.figure() plt.subplot( 121 ) plt.title( 'model' ) plt.plot( range(5), range(5) ) plt.xlabel( 'x axis' ) plt.ylabel( 'left graph' ) plt.subplot( 122 ) plt.title( 'residuals' ) plt.plot( range(5), range(5) ) plt.xlabel( 'x axis' ) plt.ylabel( 'right graph' ) plt.tight_layout(pad=4) bb = f.axes[0].get_position().transformed( f.transfigure ).get_points() bb_pad = (bb[1] - bb[0])*[.20, .10] bb_offs = bb_pad * [-.25, -.20] r = matplotlib.patches.rectangle( bb[0]-bb_pad+bb_offs, *(bb[1] - bb[0] + 2*bb_pad), zorder=-10, facecolor='0.85', edgecolor='none' ) f.patches.extend( [r] )

but seems hackish, , feels i've missed out on important. can explain what, whether there simpler/better way it, , if so, is?

since need write file, presently don't have solution.

just utilize transform kwarg rectangle, , can utilize coordinate scheme you'd like.

as simple example:

import matplotlib.pyplot plt matplotlib.patches import rectangle fig, axes = plt.subplots(3, 2) rect = rectangle((0.08, 0.35), 0.85, 0.28, facecolor='yellow', edgecolor='none', transform=fig.transfigure, zorder=-1) fig.patches.append(rect) plt.show()

however, if wanted things more robustly, , calculate extent of axes, might this:

import matplotlib.pyplot plt matplotlib.transforms import bbox matplotlib.patches import rectangle def full_extent(ax, pad=0.0): """get total extent of axes, including axes labels, tick labels, , titles.""" # text objects, need draw figure first, otherwise extents # undefined. ax.figure.canvas.draw() items = ax.get_xticklabels() + ax.get_yticklabels() # items += [ax, ax.title, ax.xaxis.label, ax.yaxis.label] items += [ax, ax.title] bbox = bbox.union([item.get_window_extent() item in items]) homecoming bbox.expanded(1.0 + pad, 1.0 + pad) fig, axes = plt.subplots(3,2) extent = bbox.union([full_extent(ax) ax in axes[1,:]]) # it's best transform figure coordinates. otherwise, won't # behave correctly when size of plot changed. extent = extent.transformed(fig.transfigure.inverted()) # can create rectangle in figure coords using "transform" kwarg. rect = rectangle([extent.xmin, extent.ymin], extent.width, extent.height, facecolor='yellow', edgecolor='none', zorder=-1, transform=fig.transfigure) fig.patches.append(rect) plt.show()

python matplotlib

No comments:

Post a Comment