Несколько подзаголовков imshow, каждый с цветовой полосой

Я хочу иметь фигуру, состоящую, скажем, из четырех сюжетных линий. Два из них обычные линейные сюжеты, два из них imshow-images.

Я могу отформатировать imshow-images для правильного построения графиков, потому что каждому из них нужна собственная цветовая полоса, измененная ось и удаленная другая ось. Это, однако, кажется абсолютно бесполезным для сюжетной линии. Может ли кто-нибудь помочь мне с этим?

Я использую это для отображения данных «обычных» графиков выше в виде цветовой карты (путем масштабирования входного массива i до [ i, i, i, i, i, i ] для 2D и вызова imshow() с ним).

Следующий код сначала отображает то, что мне нужно, в качестве подзаголовка, а второй показывает все, что я могу сделать, чего недостаточно.

#!/usr/bin/env python

import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm

s = { 't':1, 'x':[1,2,3,4,5,6,7,8], 'D':[0.3,0.5,0.2,0.3,0.5,0.5,0.3,0.4] }
width = 40

# how I do it in just one plot
tot = []
for i in range(width):
    tot.append(s['D'])

plt.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1))
plt.colorbar()
plt.axes().axes.get_xaxis().set_visible(False)
plt.yticks([0, 2, 4, 6], [s['x'][0], s['x'][2], s['x'][4], s['x'][6]])

plt.show()


f = plt.figure(figsize=(20,20))

plt.subplot(211)
plt.plot(s['x'], s['D'])
plt.ylim([0, 1])

#colorplot
sp = f.add_subplot(212)

#reshape (just necessary to see something)
tot = []
for i in range(width):
    tot.append(s['D'])

sp.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1))

    #what I can't do now but needs to be done:
    #sp.colorbar()
#sp.axes().axes.get_xaxis().set_visible(False)
#sp.yticks([0, 200, 400, 600, 800, 1000], [s['x'][0], s['x'][200], s['x'][400], s['x'][600], s['x'][800], s['x'][1000]])

plt.show()

person michael    schedule 16.08.2013    source источник
comment
Ваши примеры не работают! Можете ли вы добавить примеры данных для s и tot, чтобы мы могли видеть, что вы ищете? Для полноты было бы неплохо, если бы каждый пример заканчивался командой show.   -  person Steve Barnes    schedule 16.08.2013
comment
Извините, я добавил исполняемый код.   -  person michael    schedule 16.08.2013
comment
вам не нужны все эти cla команды. Кроме того, при размещении примеров проще всего отображать случайные данные (если только проблема не зависит от точных значений данных).   -  person tacaswell    schedule 16.08.2013
comment
Сократите этот код до минимума, необходимого для отображения вашей проблемы.   -  person tacaswell    schedule 16.08.2013
comment
Сделанный. [несколько букв для заполнения мин. char-требование]   -  person michael    schedule 16.08.2013


Ответы (1)


Вы можете использовать объектно-ориентированный интерфейс matplotlibs, а не интерфейс конечного автомата, чтобы лучше контролировать каждую ось. Кроме того, чтобы получить контроль над высотой/шириной цветовой полосы, вы можете использовать набор инструментов AxesGrid матплотлиб.

Например:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.colors import LogNorm
from matplotlib.ticker import MultipleLocator

s = {'t': 1,
     'x': [1, 2, 3, 4, 5, 6, 7, 8],
     'T': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
     'D': [0.3, 0.5, 0.2, 0.3, 0.5, 0.5, 0.3, 0.4]}

width = 40

tot = np.repeat(s['D'],width).reshape(len(s['D']), width)
tot2 = np.repeat(s['T'],width).reshape(len(s['D']), width)

fig, (ax1, ax2, ax3, ax4) = plt.subplots(1,4)

fig.suptitle('Title of figure', fontsize=20)

# Line plots
ax1.set_title('Title of ax1')
ax1.plot(s['x'], s['T'])
ax1.set_ylim(0,1)

ax2.set_title('Title of ax2')
ax2.plot(s['x'], s['D'])
# Set locations of ticks on y-axis (at every multiple of 0.25)
ax2.yaxis.set_major_locator(MultipleLocator(0.25))
# Set locations of ticks on x-axis (at every multiple of 2)
ax2.xaxis.set_major_locator(MultipleLocator(2))
ax2.set_ylim(0,1)

ax3.set_title('Title of ax3')
# Display image, `aspect='auto'` makes it fill the whole `axes` (ax3)
im3 = ax3.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1), aspect='auto')
# Create divider for existing axes instance
divider3 = make_axes_locatable(ax3)
# Append axes to the right of ax3, with 20% width of ax3
cax3 = divider3.append_axes("right", size="20%", pad=0.05)
# Create colorbar in the appended axes
# Tick locations can be set with the kwarg `ticks`
# and the format of the ticklabels with kwarg `format`
cbar3 = plt.colorbar(im3, cax=cax3, ticks=MultipleLocator(0.2), format="%.2f")
# Remove xticks from ax3
ax3.xaxis.set_visible(False)
# Manually set ticklocations
ax3.set_yticks([0.0, 2.5, 3.14, 4.0, 5.2, 7.0])

ax4.set_title('Title of ax4')
im4 = ax4.imshow(tot2, norm=LogNorm(vmin=0.001, vmax=1), aspect='auto')
divider4 = make_axes_locatable(ax4)
cax4 = divider4.append_axes("right", size="20%", pad=0.05)
cbar4 = plt.colorbar(im4, cax=cax4)
ax4.xaxis.set_visible(False)
# Manually set ticklabels (not ticklocations, they remain unchanged)
ax4.set_yticklabels([0, 50, 30, 'foo', 'bar', 'baz'])

plt.tight_layout()
# Make space for title
plt.subplots_adjust(top=0.85)
plt.show()

введите здесь описание изображения


Вы можете изменить расположение и метки делений на любой из осей с помощью методов set_ticks и set_ticklabels, как в примере выше.


Что касается того, что делает функция make_axes_locatable, с сайта matplotlib о наборе инструментов AxesGrid:

Модуль axes_divider предоставляет вспомогательную функцию make_axes_locatable, которая может быть полезна. Он берет существующий экземпляр осей и создает для него разделитель.

ax = subplot(1,1,1)
divider = make_axes_locatable(ax)

make_axes_locatable возвращает экземпляр класса AxesLocator, производного от Locator. Он предоставляет метод append_axes, который создает новые оси на заданной стороне («сверху», «справа», «снизу» и «слева») исходных осей.

person sodd    schedule 16.08.2013
comment
stackoverflow.com/questions/14254379/ ‹- подключение моего ответа на конечный автомат против OO - person tacaswell; 16.08.2013
comment
Что именно делает make_axis_locatable? - person michael; 17.08.2013
comment
Кроме того, мне нужно настроить yticks самого изображения таким образом, чтобы на данный момент yticks были индексом поля, но они представляли определенный диапазон в виде ячеек, поэтому я хотел бы написать это в ось вместо указателя. Есть ли способ заменить yticks? - person michael; 17.08.2013
comment
@michael Если я правильно понял ваш последний комментарий, вы ищете метод set_ticklabels. Я использовал это в примере (крайние правые оси). Вы можете дать список желаемых меток этому методу. Если список короче количества тиков (как в моем примере), остальные метки тиков являются пустыми строками, т.е. они не отображаются. - person sodd; 17.08.2013
comment
Идеально, похоже, я хочу, чтобы это было сейчас. Спасибо (и извините за задержку с ответом). - person michael; 28.08.2013