2013-08-12 39 views
11

Có thể có mức độ của thanh màu trong thang đo log như trong hình dưới đây không?âm mưu đường viền matplotlib: các mức độ màu tỷ lệ trong thang logarit

enter image description here

Dưới đây là một số mẫu mã, nơi nó có thể được thực hiện:

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

Tôi đang sử dụng python 2.7.3 với matplotlib 1.1.1 trên Windows 7.

+0

Thanh màu của bạn _already có_ thang đo logarit. – hooy

+2

@nordev - Tôi tin rằng OP đang hỏi làm thế nào để thiết lập định vị đánh dấu và định dạng trên thanh màu để hiển thị nhãn tại các khoảng log thông thường. –

+0

@JoeKington Ah, tôi dường như nhớ lại rằng OP trong [câu hỏi ban đầu] của mình (http://stackoverflow.com/revisions/17951672/1) muốn các dấu chọn được đặt ở các giá trị được đưa ra trong mảng 'lvls' với khoảng cách lôgarít, nhưng có lẽ tôi chỉ hiểu sai ý của anh ta là gì. Cảm ơn đã chỉ ra điều đó. – hooy

Trả lời

13

Tôi đề xuất tạo một thanh màu giả như sau (xem chú thích để giải thích):

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

này sẽ cung cấp cho bạn một âm mưu như thế này:

pseudo-colorbar

EDIT

Hoặc, sử dụng giống như các cấp độ mới và tùy chọn spacing='proportional' khi gọi colorbar:

  1. lại đặt dòng này:

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

    với những:

    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))) 
    
  2. thay thế dòng này:

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

    với điều này:

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

Và bạn sẽ kết thúc với âm mưu này:

real-colorbar

(các format chỉ thay đổi, bởi vì các dấu mới không yêu cầu 4 số thập phân)

EDIT 2
Nếu bạn muốn tự động tạo các cấp như cấp độ mà tôi đã sử dụng, bạn có thể xem xét đoạn mã sau:

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))) 
Các vấn đề liên quan