2017-05-01 105 views
0

我有一個標量函數,表示球形表面的電勢。我想繪製一個給定半徑的曲面,並根據潛在函數將它的點鏈接到一個顏色映射。如何將3d表面顏色映射映射到標量函數?

如何將該標量函數映射到曲面中的顏色映射?我懷疑它必須在傳遞給函數ax.plot_surface的參數中。我嘗試使用參數:facecolors=potencial(x,y,z),但它給了我一個ValueError: Invalid RGBA argument。縱觀source code of the third example,有:

# Create an empty array of strings with the same shape as the meshgrid, and 
# populate it with two colors in a checkerboard pattern. 
colortuple = ('y', 'b') 
colors = np.empty(X.shape, dtype=str) 
for y in range(ylen): 
    for x in range(xlen): 
     colors[x, y] = colortuple[(x + y) % len(colortuple)] 

我不明白,也沒有一個IDEIA如何鏈接到一個標量函數。

我的代碼

from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
from matplotlib import cm 
import numpy as np 
from scipy import special  

def potencial(x,y,z, a=1., v=1.): 
    r = np.sqrt(np.square(x) + np.square(y) + np.square(z))  
    p = z/r #cos(theta) 
    asr = a/r 
    s=0 
    s += np.polyval(special.legendre(1), p) * 3/2*np.power(asr, 2) 
    s += np.polyval(special.legendre(3), p) * -7/8*np.power(asr, 4) 
    s += np.polyval(special.legendre(5), p) * 11/16*np.power(asr, 6)  
    return v*s 

# Make data 
def sphere_surface(r): 
    u = np.linspace(0, 2 * np.pi, 100) 
    v = np.linspace(0, np.pi, 100) 
    x = r * np.outer(np.cos(u), np.sin(v)) 
    y = r * np.outer(np.sin(u), np.sin(v)) 
    z = r * np.outer(np.ones(np.size(u)), np.cos(v)) 
    return x,y,z 

x,y,z = sphere_surface(1.5) 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
# Plot the surface 
surf = ax.plot_surface(x,y,z, cmap=cm.coolwarm, 
         linewidth=0, antialiased=False) 
fig.colorbar(surf, shrink=0.5, aspect=5) 
# This is mapping the color to the z-axis value 

ax.set_xlabel("x") 
ax.set_ylabel("y") 
ax.set_zlabel("z") 
plt.show() 
+0

我做了葡萄牙語此相同[問題:https://pt.stackoverflow.com/questions/201673/como-um-colormap-de-uma-superfície-pode- ser-mapeado-a-uma-função-escalar –

回答

0

原則上有兩種方式上色在matplotlib表面圖。

  1. 使用cmap參數指定顏色映射。在這種情況下,顏色將根據z陣列進行選擇。如果不需要,
  2. 使用facecolors參數。這需要一組與z相同形狀的顏色。

所以在這種情況下,我們需要選擇選項2並建立一個顏色數組。 爲此,您可以選擇一個色彩地圖。顏色映射將0和1之間的值映射爲顏色。由於電位的值遠高於和低於此範圍,因此需要將它們歸一化到[0,1]範圍內。
Matplotlib已經提供了一些輔助函數來執行這種規範化操作,並且由於潛力具有1/x依賴性,所以對數色標可能是合適的。

在結束時facecolors因此可以給出的陣列

colors = cmap(norm(potential(...))) 

現在的缺失位是彩條。爲了將顏色條連接到曲面圖的顏色,我們需要手動設置帶有顏色貼圖和標準化實例的ScalarMappable,然後我們可以將顏色貼圖提供給顏色條。

sm = plt.cm.ScalarMappable(cmap=plt.cm.coolwarm, norm=norm) 
sm.set_array(pot) 
fig.colorbar(sm, shrink=0.5, aspect=5) 

這裏是完整的例子。

from __future__ import division 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
import matplotlib.colors 
import numpy as np 
from scipy import special  

def potencial(x,y,z, a=1., v=1.): 
    r = np.sqrt(np.square(x) + np.square(y) + np.square(z))  
    p = r/z #cos(theta) 
    asr = a/r 
    s=0 
    s += np.polyval(special.legendre(1), p) * 3/2*np.power(asr, 2) 
    s += np.polyval(special.legendre(3), p) * -7/8*np.power(asr, 4) 
    s += np.polyval(special.legendre(5), p) * 11/16*np.power(asr, 6)  
    return v*s 

# Make data 
def sphere_surface(r): 
    u = np.linspace(0, 2 * np.pi, 100) 
    v = np.linspace(0, np.pi, 100) 
    x = r * np.outer(np.cos(u), np.sin(v)) 
    y = r * np.outer(np.sin(u), np.sin(v)) 
    z = r * np.outer(np.ones(np.size(u)), np.cos(v)) 
    return x,y,z 

x,y,z = sphere_surface(1.5) 
pot = potencial(x,y,z) 


norm=matplotlib.colors.SymLogNorm(1,vmin=pot.min(),vmax=pot.max()) 
colors=plt.cm.coolwarm(norm(pot)) 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
# Plot the surface 
surf = ax.plot_surface(x,y,z, facecolors=colors, 
         linewidth=0, antialiased=False) 
# Set up colorbar 
sm = plt.cm.ScalarMappable(cmap=plt.cm.coolwarm, norm=norm) 
sm.set_array(pot) 
fig.colorbar(sm, shrink=0.5, aspect=5) 


ax.set_xlabel("x") 
ax.set_ylabel("y") 
ax.set_zlabel("z") 
plt.show() 

enter image description here

+0

謝謝你的回答。我將它翻譯成葡萄牙語(https://pt.stackoverflow.com/a/201691/47184)。 –