繁体   English   中英

将Matplotlib注释与颜色栏对齐

[英]Aligning matplotlib annotation to colorbar

我想绘制一个彩条,并在其底部对齐一个字符串(序列)。 我在下面发布了一个工作示例,但这并不是一个理想的解决方案,因为有一些硬编码值。 我还有其他/更好/更智能的方式可以做到这一点吗? 动态地适应各种字体大小将是理想的。

要求:

  1. 文本必须在Web浏览器中作为连续的一行可以选择(webbrowsers中的svg格式允许我们单击并拖动选择的matplotlib文本)
    • 我想选择文本的各个部分。 即,如果我根据分数列表看到一个特别有趣的区域,我想选择该部分并将其复制到我的剪贴板中
  2. 文字必须与它后面的颜色条完全对齐。

如果要使每个字母成为一个轴刻度,它们将不再是我不希望选择的单个连续字符串(实际上是换行符分隔它们)。

import numpy as np
import matplotlib.pyplot as plt
from numpy import array
from mpl_toolkits.axes_grid1 import make_axes_locatable


myseq = "AERGERGEREKLKLKLLLKKLWEWRKLEWRLWKERLKKLYKLTELWLKLRWELKHLW"
scorelist = [np.random.randint(0,5) for x in myseq ]

# SET FIGURE SIZE, Not ideal, but sort of works
fig = plt.figure(figsize=(len(myseq)/6.64175,5)) # MAGIC NUMBER?
ax = plt.subplot()
scorearray = array([scorelist,scorelist])

# Plotting the colorbar
cmap = plt.cm.rainbow
im = ax.imshow(scorearray, extent=[-0.5, len(scorelist)-0.5, 0, 5], cmap=cmap)
divider = make_axes_locatable(ax)
cax = divider.append_axes("top", size="5%", pad=0.04)
cbar = plt.colorbar(im, cax=cax, orientation='horizontal')
cbar.ax.xaxis.set_ticks_position('top')
ax.yaxis.set_visible(False)
ax.text(-0.5,-1.1,myseq, size=14, name='Courier new')

# Use 1 indexing for human counting
ax.set_xticks([0] + list(np.arange(9, len(myseq), 10)));
ax.set_xticklabels(['1'] + [str(i) for i in range(10, len(myseq), 10)]);
ax.set_xticks(np.arange(-0.5, len(myseq), 1), minor=True);

ax.grid(which='minor', color='w', linestyle='-', linewidth=2)
plt.rcParams['svg.fonttype'] = 'none'
# plt.show()
plt.savefig("alignment.svg")

在此处输入图片说明

基本上,我希望能够查看评分表的颜色条表示形式,并手动选择我觉得有趣的区域,并要求评分表与我的图上文字很好地对齐。

请注意,以下内容实际上不会产生正确的svg输出。 虽然有人可能仍将其用于png输出。

一种选择是根据给定的文本计算所需的图形宽度。 因此,想法是先创建具有某种字体和大小的文本,然后“测量”它的大小,然后根据该数字设置轴的宽度。 现在,轴宽度本身不是直接可用的,而是取决于figwidth = axes width/(margin_right - margin_left)设置的图形宽度和边距。 然后,我们将文本宽度设置为轴宽。 文本本身以中心对齐的方式放置在轴的中间,这样,一旦轴的宽度与文本的宽度相同,它们(几乎)就会完全对齐。

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

#### free input parameters ####
figheight = 4 # inch
subplotpars = dict(left=0.1, right=0.9)
fontsize = 16
fontname = 'Courier new' # need to choose a monospace font here

myseq = "AERGERGEREKLKLKLLLKKLWEWRKLEWRLWKERLKKLYKLTELWLKLRWELKHLW"
scorelist = [np.random.randint(0,5) for x in myseq ]

#### automatic plotting ####
fig = plt.figure(figsize=(6,figheight)) # at this point only height will matter
fig.subplots_adjust(**subplotpars)
ax = plt.subplot()
scorearray = np.array([scorelist,scorelist])

# Plotting the colorbar
cmap = plt.cm.rainbow
im = ax.imshow(scorearray, extent=[-0.5, len(scorelist)-0.5, 0, 5], cmap=cmap)
divider = make_axes_locatable(ax)
cax = divider.append_axes("top", size="5%", pad=0.04)
cbar = plt.colorbar(im, cax=cax, orientation='horizontal')
cbar.ax.xaxis.set_ticks_position('top')
ax.yaxis.set_visible(False)

# position text centered at middle of axes
text = ax.text(0.5,-0.08, myseq, size=fontsize, name=fontname, 
               transform=ax.transAxes, va="top", ha="center")
# draw canvas to fix positions of elements
fig.canvas.draw()
bbox = text.get_window_extent()
# calculate figure width according to width of text
figwidth=bbox.width/float(fig.dpi)/(subplotpars["right"]-subplotpars["left"])
fig.set_size_inches((figwidth, fig.get_size_inches()[1]))


ax.set_xticks([0] + list(np.arange(9, len(myseq), 10)));
ax.set_xticklabels(['1'] + [str(i) for i in range(10, len(myseq), 10)]);
ax.set_xticks(np.arange(-0.5, len(myseq), 1), minor=True);
ax.xaxis.set_tick_params(pad=10)

ax.grid(which='minor', color='w', linestyle='-', linewidth=2)
plt.rcParams['svg.fonttype'] = 'none'
plt.show()

在此处输入图片说明

现在,使用免费的输入参数并观察更改相对容易。
请注意,原则上也可以自动确定轴与文本之间的填充(此处硬编码为0.08)以及轴与刻度标签之间的填充(此处硬编码为10点); 但由于我不知道是否需要这样做,我将其遗漏了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM