Ответ 1
Эта комбинация (и значения, близкие к этим), кажется, "магически" работает для меня, чтобы сохранить цветную шкалу, масштабированную до графика, независимо от размера дисплея.
plt.colorbar(im,fraction=0.046, pad=0.04)
Я использую quadmesh
для создания простой полярной проекции. Здесь минимальный script, который производит в основном то, что я пытаюсь сделать:
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
def make_plot(data,fig,subplot):
nphi,nt = data.shape
phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
theta_coords = np.linspace(0,np.radians(35),nt+1)
ax = fig.add_subplot(subplot,projection='polar')
ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
theta,phi = np.meshgrid(phi_coords,theta_coords)
quadmesh = ax.pcolormesh(theta,phi,data)
ax.grid(True)
fig.colorbar(quadmesh,ax=ax)
return fig,ax
a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)
fig.savefig('test.png')
Вышеупомянутый script создает график, который выглядит следующим образом:
Я хотел бы, чтобы цветные панели:
Есть ли какой-нибудь трюк, чтобы сделать эту работу должным образом? (Обратите внимание, что этот макет не единственный, который я буду использовать, например, я мог бы использовать макет 1x2 или макет 4x4... Кажется, должен быть какой-то способ масштабирования цветной панели до той же высоты, что и связанный сюжет...)
Эта комбинация (и значения, близкие к этим), кажется, "магически" работает для меня, чтобы сохранить цветную шкалу, масштабированную до графика, независимо от размера дисплея.
plt.colorbar(im,fraction=0.046, pad=0.04)
Вы можете сделать это с помощью комбинации pad
, shrink
и aspect
kwargs:
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
def make_plot(data,fig,subplot):
nphi,nt = data.shape
phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
theta_coords = np.linspace(0,np.radians(35),nt+1)
ax = fig.add_subplot(subplot,projection='polar')
ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
theta,phi = np.meshgrid(phi_coords,theta_coords)
quadmesh = ax.pcolormesh(theta,phi,data)
ax.grid(True)
cb = fig.colorbar(quadmesh,ax=ax, shrink=.5, pad=.2, aspect=10)
return fig,ax,cb
a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)
Наилучшее значение для этих параметров будет зависеть от соотношения сторон осей.
Размер осей, по-видимому, не увязывается с термоусадочной пленкой, поэтому в компоновке 1x2 имеется много пространства над и под участком, которые являются частью объекта осей, но пустыми. Размер цветовой полосы зависит от размера прямоугольника, а не от округлого размера, поэтому значения по умолчанию не работают. Вероятно, есть способ сделать термоусадочную пленку, но я не знаю, как это сделать.
Альтернативный метод заключается в том, чтобы заставить фигуру быть правильным соотношением сторон ex:
fig.set_size_inches(10, 4) # for 1x2
fig.set_size_inches(4, 10) # for 2x1
что делает квадраты подстроки квадратными, поэтому значения по умолчанию более или менее работают.
Автоматическое масштабирование цветовой полосы, как известно, сложно. Попытка применить работу, описанную в конце этой страницы, не работала для меня ни с вашим примером, ни с моими попытками с использованием объекта Axes3D
, Взглянув на сигнатуру вызова colorbar
, аргумент ключевого слова ax
представляет собой "объект, из которого пространство для новых осей цветной панели будут украдены". Это объясняет, почему цветовая полоса перекрывает 6. Итак, мы должны поддерживать двойной Axes
. К сожалению, необходимость поддерживать дополнительные оси означает много ручного взлома позиции. Я объединил следующее:
#!/usr/bin/env python
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
N, M = 360, 71
phi_coords = np.linspace(0, np.pi*2, M+1) -np.pi/2
theta_coords = np.linspace(0, np.radians(35), N+1)
theta, phi = np.meshgrid(phi_coords, theta_coords)
# Original method
a = np.zeros((N,M)) + np.arange(N)[:,None]
ax1 = fig.add_subplot(1,2,1, projection="polar")
ax1.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax1.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
quadmesh = ax1.pcolormesh(theta, phi, a)
fig.colorbar(quadmesh,ax=ax1)
# Use ``add_axes`` to make a ``cax``
b = np.random.random((N,M))
ax2 = fig.add_subplot(1,2,2, projection="polar")
ax2.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax2.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
quadmesh = ax2.pcolormesh(theta, phi, b)
# <hack>
# Hack to force the drawing of the image.
print(ax2.get_position())
import tempfile
with tempfile.SpooledTemporaryFile() as fid:
fig.savefig(fid, format="png")
# </hack>
# Now the axes has been scaled to the final size.
bbox = ax2.get_position()
print(bbox)
cax = fig.add_axes(
[bbox.xmax*1.03, bbox.ymin, bbox.width*0.08, bbox.height]
)
fig.colorbar(quadmesh,cax=cax)
fig.savefig('test.png')
Левое изображение совпадает с оригиналом, но изображение правой руки имеет смещение цветовой полосы от полярного графика, а высота бара соответствует полярному графику. Как вы можете видеть, мне пришлось вынудить фигуру рисовать, чтобы получить размер оси справа для участка левой руки. Если вы не нажмете перерисовать, размер цветовой полосы будет основываться на размере исходных осей, и вы получите оси того же размера, что и левый. На данный момент я не нашел способ сообщить Axes
, чтобы цветная строка автоматически отслеживала основной Axes
для изменения размера.