2013-05-22 5 views
11

Я использую quadmesh для создания простой полярной проекции. Вот минимальный сценарий, который производит в основном то, что я пытаюсь сделать:matplotlib colorbar размещение и размер

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') 

выше сценарий создает сюжет, который выглядит следующим образом:

enter image description here

Я хотел бы, ColorBars к:

  1. Не накладывать этикетку 6.
  2. можно масштабировать таким образом, чтобы они были примерно такой же высоты, как и график.

Есть ли какой-либо трюк, чтобы сделать эту работу должным образом? (Обратите внимание, что этот макет не единственный, который я буду использовать, например, я мог бы использовать макет 1x2 или макет 4x4 ... Кажется, должен быть какой-то способ масштабирования цветной панели до той же высоты, что и связанный сюжет ...)

ответ

12

Вы можете сделать это с помощью комбинации 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) 

figure.colorbar doc

лучшее значение для этих параметров будет зависеть от аспекта отношение осей.

Размер осей, кажется, не увязан с термоусадочной оболочкой на полярном участке, поэтому в расположении 1x2 имеется много пространства над и под участком, которые являются частью объекта осей, но пустыми. Размер цветовой полосы зависит от размера прямоугольника, а не от округлого размера, поэтому значения по умолчанию не работают. Вероятно, есть способ сделать термоусадочную пленку, но я не знаю, как это сделать.

Альтернативный метод, чтобы заставить вашу фигуру, чтобы быть правильным соотношением сторон например:

fig.set_size_inches(10, 4) # for 1x2 
fig.set_size_inches(4, 10) # for 2x1 

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

+0

Это работает (более или менее) для компоновки 2x1, но не для макета 1x2 (тогда цветная панель становится слишком малой). Я действительно ищу макет независимого решения. Что касается моих rcparams, я не уверен. У меня нет никакого rc-файла (насколько мне известно), а 'print matplotlib.rcParams ['bounding_box_tight']' приводит к 'KeyError'. – mgilson

+0

@mgilson У меня есть ключ, который помнят неправильно, см. Править. Я думаю, что основная проблема заключается в том, что ограничивающая рамка объекта «axes» не сжимается вокруг полярного графика, и все длины цветных баров привязаны к ограничивающей рамке размера. – tacaswell

+0

Я все еще получаю 'KeyError' для' savefig.bbox'. Я даже попробовал '[v для v в matplotlib.rcParams.values ​​(), если isinstance (v, str) и 'tight' in v]', который дал мне пустой список. Я использую версию 1.1.1. – mgilson

15

Эта комбинация (и значения рядом с ними), кажется, «магически» работает для меня, чтобы сохранить цветную шкалу, масштабированную до графика, независимо от того, какой размер дисплея.

plt.colorbar(im,fraction=0.046, pad=0.04) 
+1

Это волшебство! –

+1

Это отлично сработало для меня. Использование последней версии matplotlib (на момент написания). Спасибо! – user3125347

0

Автоматическое масштабирование цветовой полосы, как известно, сложное. Попытка применить работу, описанную в конце this page, не работала для меня ни с вашим примером, ни с моими попытками с использованием объекта 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 для изменения размера.

Смежные вопросы