2013-08-12 30 views
11

Aşağıdaki resimde olduğu gibi günlük düzeyinde colorbar düzeylerine sahip olmak mümkün olabilir mi?matplotlib kontur çizimi: logaritmik ölçekte orantısal colorbar seviyeleri

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.colors import LogNorm 
delta = 0.025 

x = y = np.arange(0, 3.01, delta) 
X, Y = np.meshgrid(x, y) 
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
Z = 1e6 * (Z1* Z2) 

fig=plt.figure() 
ax1 = fig.add_subplot(111) 
lvls = np.logspace(0,4,20) 
CF = ax1.contourf(X,Y,Z, 
     norm = LogNorm(), 
     levels = lvls 
     ) 
CS = ax1.contour(X,Y,Z, 
     norm = LogNorm(), 
     colors = 'k', 
     levels = lvls 
     ) 
cbar = plt.colorbar(CF, ticks=lvls, format='%.4f') 
plt.show() 

enter image description here

Ben

Windows 7'de matplotlib 1.1.1 ile piton 2.7.3 kullanıyorum: Burada

enter image description here

o uygulanabilecek bazı örnek kod
+0

Colorbar'ınız _already_ bir logaritmik ölçeğe sahiptir. – hooy

+2

@nordev - OP'nin, normal günlük aralıklarında etiketleri görüntülemek için işaret çubuğunu ve biçimlendiriciyi renk çubuğunda nasıl ayarlayacağını sorduğuna inanıyorum. –

+0

@JoeKington Ah, OP'nin kendi orijinal sorgusunda (http://stackoverflow.com/revisions/17951672/1) işaretlerin lvls dizisiyle verilen değerlere yerleştirilmesini istediğini hatırladım. Logaritmik boşluk, ama belki de ne demek istediğimi yanlış anladım. İşaret ettiğin için teşekkürler. – hooy

cevap

13

Aşağıdaki gibi sözde bir colorbar oluşturmayı öneriyorum (açıklamalara bakın):

çağrılırken spacing='proportional' seçeneği

pseudo-colorbar

DÜZENLEMEYİ

Veya, yeni seviyeleri gibi bir şey kullanmak ve:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.colors import LogNorm 
import matplotlib.gridspec as gridspec 

delta = 0.025 

x = y = np.arange(0, 3.01, delta) 
X, Y = np.meshgrid(x, y) 
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
Z = 1e6 * (Z1 * Z2) 

fig=plt.figure() 

# 
# define 2 subplots, using gridspec to control the 
# width ratios: 
# 
# note: you have to import matplotlib.gridspec for this 
# 
gs = gridspec.GridSpec(1, 2,width_ratios=[15,1]) 

# the 1st subplot 
ax1 = plt.subplot(gs[0]) 

lvls = np.logspace(0,4,20) 

CF = ax1.contourf(X,Y,Z, 
        norm = LogNorm(), 
        levels = lvls 
       ) 
CS = ax1.contour(X,Y,Z, 
       norm = LogNorm(), 
       colors = 'k', 
       levels = lvls 
       ) 

# 
# the pseudo-colorbar 
# 

# the 2nd subplot 
ax2 = plt.subplot(gs[1])   

# 
# new levels! 
# 
# np.logspace gives you logarithmically spaced levels - 
# this, however, is not what you want in your colorbar 
# 
# you want equally spaced labels for each exponential group: 
# 
levls = np.linspace(1,10,10) 
levls = np.concatenate((levls[:-1],np.linspace(10,100,10))) 
levls = np.concatenate((levls[:-1],np.linspace(100,1000,10))) 
levls = np.concatenate((levls[:-1],np.linspace(1000,10000,10))) 

# 
# simple x,y setup for a contourf plot to serve as colorbar 
# 
XC = [np.zeros(len(levls)), np.ones(len(levls))] 
YC = [levls, levls] 
CM = ax2.contourf(XC,YC,YC, levels=levls, norm = LogNorm()) 
# log y-scale 
ax2.set_yscale('log') 
# y-labels on the right 
ax2.yaxis.tick_right() 
# no x-ticks 
ax2.set_xticks([]) 

plt.show() 

Bu, böyle bir arsa verecek

  1. re Bununla

    cbar = plt.colorbar(CF, ticks=lvls, format='%.4f') 
    

    :

    cbar = plt.colorbar(CF, ticks=lvls, format='%.2f', spacing='proportional') 
    

lvls = np.linspace(1,10,5) 
lvls = np.concatenate((lvls[:-1],np.linspace(10,100,5))) 
lvls = np.concatenate((lvls[:-1],np.linspace(100,1000,5))) 
lvls = np.concatenate((lvls[:-1],np.linspace(1000,10000,5))) 
  • bu satırı değiştirin: Bunlarla

    lvls = np.logspace(0,4,20) 
    

    : Bu satırı koyun

    Ve bu arsa ile sona erecek:

    real-colorbar

    (yeni kene 4 ondalık basamak gerekmez çünkü format yalnızca değiştirildi)

    DÜZENLEME 2
    Eğer Kullandığım gibi otomatik olarak seviye oluşturmak istedim, bu kod parçasını düşünebilirsiniz:

    levels = [] 
    LAST_EXP = 4 
    N_LEVELS = 5 
    for E in range(0,LAST_EXP): 
        levels = np.concatenate((levels[:-1],np.linspace(10**E,10**(E+1),N_LEVELS)))