我想绘制一个颜色条,其中一个字符串(序列)与其底部对齐。我在下面发布了一个工作示例,但它并不是一个理想的解决方案,因为有一些硬编码值。 有没有其他/更好/更聪明的方法可以做到这一点?动态调整各种字体大小是理想的。
要求:
如果你要使每个字母成为一个轴,那么它们就不再可以选择作为一个连续的字符串(实际上是换行符将它们分开),这是我不想要的。
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")
基本上我希望能够查看得分列表的颜色栏表示,并手动选择我感兴趣的区域,并要求得分列表很好地与我的图表文本对齐。
答案 0 :(得分:0)
请注意,以下内容实际上并不会产生正确的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个点);但由于我不知道是否需要,我把它留了出来。