2

I want generate a contour plot/heat map with a color bar and then add an annotation box. This figure is ugly, but gets at what I want:

example image

add_subplot() is not enough. If I try to put everything in the same subplot, the box gets covered up. I can get around this by making it dragable and then futzing with the size of the image, but this is no good. I am going to have to make several of these images, all of a standard size, and I can't fight with the size over and over again.

I tried axes() as well, putting the box in a separate axis. But that generates a new window for plotting that covers up most of my color bar. I guess there would be ways to make the window completely transparent. But when I get to that point, I think my approach must be completely wrong.

This doesn't seem like it should be so hard. Any ideas?

4

3 回答 3

5

等高线图的注释框:

更好的图表

这样做:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from numpy.random import randn

from mpl_toolkits.axes_grid1.axes_divider import HBoxDivider
import mpl_toolkits.axes_grid1.axes_size as Size


def make_heights_equal(fig, rect, ax1, ax2, ax3, pad):
    # pad in inches

    h1, v1 = Size.AxesX(ax1), Size.AxesY(ax1)
    h2, v2 = Size.AxesX(ax2, 0.1), Size.AxesY(ax2)
    h3, v3 = Size.AxesX(ax3), Size.AxesY(ax3)

    pad_v = Size.Scaled(1)
    pad_h = Size.Fixed(pad)

    my_divider = HBoxDivider(fig, rect,
                             horizontal=[h1, pad_h, h2, pad_h, h3],
                             vertical=[v1, pad_v, v2, pad_v, v3])


    ax1.set_axes_locator(my_divider.new_locator(0))
    ax2.set_axes_locator(my_divider.new_locator(2))
    ax3.set_axes_locator(my_divider.new_locator(4))


# Make plot with vertical (default) colorbar
fig = plt.figure()
img_ax = fig.add_subplot(131)
bar_ax = fig.add_subplot(132)
ann_ax = fig.add_subplot(133)

data = np.clip(randn(250, 250), -1, 1)

im = img_ax.imshow(data, interpolation='nearest', cmap=cm.coolwarm)

# Add colorbar, make sure to specify tick locations to match desired ticklabels
cbar = fig.colorbar(im, cax=bar_ax, ticks=[-1, 0, 1])
cbar.ax.set_yticklabels(['< -1', '0', '> 1'])# vertically oriented colorbar

ann_ax.axis('off')

ann_ax.annotate("Hello, I'm an annotation", (0.5, 0.5),
                 xycoords="axes fraction", va="center", ha="center",
                 bbox=dict(boxstyle="round, pad=1", fc="w")) 

make_heights_equal(fig, 111, img_ax, bar_ax, ann_ax, 0.2)

plt.savefig("try.png")
于 2013-06-12T19:26:45.667 回答
2

这是一个相当简单的解决方案,使用make_axes_locatable函数 from mpl_toolkits.axes_grid1,因为这使颜色条与图像具有相同的高度。此外,设置颜色栏相对于Axes.

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib import cm
from numpy.random import randn

# Make plot with vertical (default) colorbar
fig = plt.figure()
ax = fig.add_subplot(121, aspect='equal')
ax2 = fig.add_subplot(122, aspect='equal')
ax2.axis('off')
divider = make_axes_locatable(ax)

# Specify placement, width and padding of colorbar
cax = divider.append_axes("right", size="10%", pad=0.1)

data = np.clip(randn(250, 250), -1, 1)

im = ax.imshow(data, interpolation='nearest', cmap=cm.coolwarm)
ax.set_title('Title')

# Add colorbar, make sure to specify tick locations to match desired ticklabels
cbar = fig.colorbar(im, cax=cax, ticks=[-1, 0, 1])
cbar.ax.set_yticklabels(['< -1', '0', '> 1'])# vertically oriented colorbar

# Add text
boxtext = \
"""Text box
Second line
Third line"""

props = dict(boxstyle='round, pad=1', facecolor='white', edgecolor='black')
ax2.text(0.15, 0.85, boxtext, ha='left', va='top', transform=ax2.transAxes, bbox=props)

#plt.tight_layout()
plt.savefig(r'D:\image.png', bbox_inches='tight', dpi=150)

在此处输入图像描述

于 2013-06-12T20:14:06.400 回答
1

这就是我要做什么:

import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from numpy.random import randn
import pickle

data  = np.clip(randn(250, 250), -1, 1)

fig3 = plt.figure()

ax1 = fig3.add_axes([.1,.1,.55,.8])
ax2 = fig3.add_axes([.7,.1,.05,.8])
ax3 = fig3.add_axes([.78,.1,.1,.8])
ax3.axis('off')

hm = ax1.pcolor(data, cmap=cm.coolwarm) 

plt.colorbar(hm,cax = ax2)

bbox_args = dict(boxstyle='square',facecolor='white')
ann = ax3.annotate('More info here', xy=(.2,.8),
              xytext=(.2,.8), transform=ax3.transAxes, bbox=bbox_args)

plt.show()

结果是:

上面代码的示例图

并不是说这比提供的其他答案更好(对此我非常感激!)但我可以理解它(!)并且很容易调整它。我不会选择自己的答案,因为阅读其他答案让我按照自己需要的思路进行思考。(特别是,不知道轴('off')并且没有考虑将颜色条放在它自己的轴对象中。我有没有提到我是一个菜鸟?)无论如何,如果有人想要第三种选择,这就是这个。

于 2013-06-12T22:58:30.473 回答