Систематический и простой подход, хотя и немного более громоздким на старте, чтобы использовать matplotlib.gridspec.GridSpec
.
Сначала настроить сетку:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
fig = plt.figure()
gs = GridSpec(2, 3, width_ratios=[10, 1, 1], height_ratios=[1, 10])
Это дает нам сетку 2 строк и 3 столбцов, где нижняя левая ось будет 10х10 и другие оси будут либо 10x1 или 1x10 в относительных размерах , Эти коэффициенты можно настроить по своему вкусу. Обратите внимание, что верхние центральные/правые оси будут пустыми.
big_ax = fig.add_subplot(gs[1,0]) # bottom left
top_ax = fig.add_subplot(gs[0,0]) # top left
right_ax = fig.add_subplot(gs[1,1]) # bottom center
cbar_ax = fig.add_subplot(gs[1,2]) # bottom right
Я буду использовать общую картину генома я нашел через Google для верхнего и правого изображения:
и будет генерировать случайные Heatmap. Я использую imshow(aspect='auto')
, так что объекты изображения и тепловая карта занимают все пространство соответствующих осей (в противном случае они будут перекрывать отношения высоты/ширины, заданные сеткой).
im = plt.imread('/path/to/image.png')
# Plot your heatmap on big_ax and colorbar on cbar_ax
heatmap = big_ax.imshow(np.random.rand(10, 10), aspect='auto', origin='lower')
cbar = fig.colorbar(heatmap, cax=cbar_ax)
# Show your images on top_ax and right_ax
top_ax.imshow(im, aspect='auto')
# need to rotate my image.
# you may not have to if you have two different images
from scipy import ndimage
right_ax.imshow(ndimage.rotate(im, 90), aspect='auto')
# Clean up the image axes (remove ticks, etc.)
right_ax.set_axis_off()
top_ax.set_axis_off()
# remove spacing between axes
fig.subplots_adjust(wspace=0.05, hspace=0.05)
Это не супер гламурные (особенно с реактивным палитрой по умолчанию), но вы можете легко использовать это, чтобы воспроизвести рисунок вашего OP.
Edit: Так что, если вы хотите создать что геном-подобный участок на верхней и правой, вы могли бы попробовать что-то подобное для верхней панели:
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection
# draw the black line
top_ax.axhline(0, color='k', zorder=-1)
# box x-coords and text labels
boxes = zip(np.arange(0.1, 1, 0.2), np.arange(0.2, 1, 0.2))
box_text = ('A1', 'B1', 'B2', 'A2')
# color indicators for boxes
colors = (0, 1, 1, 0)
# construct Rects
patches = [Rectangle(xy=(x0, -1), width=(x1-x0), height=2) for x0,x1 in boxes]
p = PatchCollection(patches, cmap='jet')
# this maps the colors in [0,1] to the cmap above
p.set_array(np.array(colors))
top_ax.add_collection(p)
# add text
[top_ax.text((x0+x1)/2., 1.2, text, ha='center')
for (x0,x1), text in zip(boxes, box_text)]
# adjust ylims
top_ax.set_ylim(-2, 2)
Для что-то в правой оси, вы можете сделать то же самое, но используйте axvline
и поменяйте x-coords на y-coords.
right_ax.axvline(0, color='k', zorder=-1)
patches = [Rectangle(xy=(-1, y0), width=2, height=(y1-y0)) for y0, y1 in boxes]
p = PatchCollection(patches, cmap='jet')
p.set_array(np.array(colors))
right_ax.add_collection(p)
[right_ax.text(1.2, (y0+y1)/2., text, va='center')
for (y0, y1), text in zip(boxes, box_text)]
right_ax.set_xlim(-2,2)
Эти изменения приводят к чему-то вроде:
Большое спасибо за ваш ответ. Но в ваших случаях панель просто считывается с рисунка, поэтому трудно масштабировать размер и точно соответствовать значению оси X. Так или иначе, мы можем построить планку самим собой? Благодаря! –
@ZhouHongyu Проверьте изменения. – wflynny
Большое спасибо за редактирование !! Я попробую этот метод сейчас! –