В следующем подходе для отображения информации на экране используется mplcursors
, а также сохраняется файл изображения, который можно распечатать.
При печати на бумаге формата A4 размер каждого маленького квадрата будет около 2x2 мм, поэтому вам могут пригодиться хороший принтер и зеркало. Возможно, вы захотите поэкспериментировать с размером шрифта.
На экране mplcursors
отображает всплывающую аннотацию при нажатии на маленький квадрат. При увеличении требуется двойной щелчок, чтобы не мешать работе с масштабированием. mplcursors
также имеет режим «зависания», но при увеличении масштаба информация не отображается.
Некоторый код, демонстрирующий, как это может работать:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import mplcursors
import numpy as np
P = [1, 4, 11, 18, 20, 39, 40, 41, 41, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 73, 73, 73, 74, 74, 74, 74, 74, 74, 75, 75, 75, 71]
N = [2, 3, 11, 19, 25, 49, 48, 50, 54, 101, 102, 103, 103, 106, 106, 100, 103, 106, 106, 107, 109, 105, 106, 109, 104, 107, 109, 110, 111, 112, 108, 109, 109, 101]
B = np.random.rand(34)
# create the array to use with imshow()
A = np.zeros((max(N) + 1, max(N) + 1))
for i, j, k in zip(N, P, B):
A[i, j] = k
fig, ax = plt.subplots(figsize=(21, 15))
img = ax.imshow(A, norm=colors.LogNorm(), cmap='jet', origin='lower')
plt.colorbar(img)
for n, p in zip(N, P):
plt.text(p, n, "%s\n%s\n%5.1E"%(p,n,A[n,p]), size=2,
va="center", ha="center", multialignment="left")
cursor = mplcursors.cursor(img, hover=False)
@cursor.connect("add")
def on_add(sel):
i,j = sel.target.index
if A[i][j] == 0:
sel.annotation.set_visible(False)
else:
sel.annotation.set_text(f'P: {j}\nN: {i}\n{A[i][j]:.3f}')
plt.tight_layout()
plt.savefig('test.png', dpi=300)
plt.show()
Слева показано, как он будет выглядеть на экране при увеличении и двойном щелчке по квадрату. Справа, как будет выглядеть изображение для печати при увеличении.
![resulting plots](https://i.stack.imgur.com/CEtH6.png)
Чтобы получить текст, который увеличивается при увеличении, TextPath
необходимо, как объяснено в этом посте . Поскольку TextPath
на самом деле не работает с несколькими строками и выравниваниями, код вычисляет позиции. Кроме того, в зависимости от цвета поля текст легче читать, когда он белый. Вам нужно проверить, какие значения являются хорошими срезами в вашей ситуации и цветовой карте.
Чтобы справиться с пустым пространством, вы можете увеличить данные до трех мест. Приведенный ниже код создает подзаговор для каждой из этих областей.
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.textpath import TextPath
from matplotlib.patches import PathPatch
from matplotlib.ticker import MaxNLocator
import numpy as np
P = [1, 4, 11, 18, 20, 39, 40, 41, 41, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 73, 73, 73, 74, 74, 74, 74, 74, 74, 75, 75, 75, 71]
N = [2, 3, 11, 19, 25, 49, 48, 50, 54, 101, 102, 103, 103, 106, 106, 100, 103, 106, 106, 107, 109, 105, 106, 109, 104, 107, 109, 110, 111, 112, 108, 109, 109, 101]
B = np.random.rand(34)
# create the array to use with imshow()
A = np.zeros((max(N) + 1, max(N) + 1))
for i, j, k in zip(N, P, B):
A[i, j] = k
plot_limits = [[[0, 19], [1, 20]],
[[38, 42], [47 - 1, 55 + 2]], # second subplot with higher y-range to better fit with the rest
[[70, 76], [99, 113]],
[[0, 0.05], [0, 1]]] # separate subplot for the colorbar
width_ratios = [(lim[0][1] - lim[0][0] ) / (lim[1][1] - lim[1][0]) for lim in plot_limits]
fig, ax = plt.subplots(figsize=(16, 8), ncols=4, gridspec_kw={'width_ratios': width_ratios})
for i in range(3):
img = ax[i].imshow(A, norm=colors.LogNorm(), cmap='jet', origin='lower')
for n, p in zip(N, P):
textsize = 0.3
for line, label in zip((n + 0.2, n - 0.1, n - 0.4), (f"{p}", f"{n}", f"{A[n, p]:.3f}")):
tp = TextPath((p - 0.4, line), label, size=0.3)
ax[i].add_patch(PathPatch(tp, color="black" if 0.08 < A[n, p] < 0.7 else "white"))
ax[i].xaxis.set_major_locator(MaxNLocator(integer=True))
ax[i].yaxis.set_major_locator(MaxNLocator(integer=True))
ax[i].set_xlim(plot_limits[i][0])
ax[i].set_ylim(plot_limits[i][1])
plt.colorbar(img, cax=ax[3])
plt.tight_layout()
plt.show()
Вот как это выглядит:
![triple plot version](https://i.stack.imgur.com/2DVlk.png)