2015-09-08 76 views
0

我試圖繪製一個3d表面,其中三個維度中的每個值分別表示顏色和每個座標是x,y,z的函數。一種numpy.pcolormesh,但在4D,而不是3D。 3D圖由下式給出:(python)繪製三維表面作爲第四維,colormap作爲第四維,函數的x,y,z

from mpl_toolkits.mplot3d import Axes3D 
from matplotlib import cm 
fig = plt.figure() 
ax = fig.gca(projection='3d') 
x = np.logspace(-1.,np.log10(5),50) 
y = np.linspace(6,9,50) 
z = np.linspace(-1,1,50) 
colors = LikeBeta(y,range(50),range(50)) 
ax.plot_trisurf(x,y,z,cmap=colors,linewidth=0.2) 

其中

def LikeBeta(rho0,r0,beta): 
    M0 = 10**rho0*r0_array[r0]**3 
    I = cst*M0*sigma_los_beta[beta,:,r0] 
    S = dv**2+I 
    res = (np.log(S) + (v-u)**2/S).sum() 
    return res/2. 

也許cmap=colors是錯誤的,但問題不在於此。我得到以下錯誤:

----> 8 colors = LikeBeta(y,range(50),range(50)) 
----> 4  I = cst*M0*sigma_los_beta[beta,:,r0] 
    ValueError: operands could not be broadcast together with shapes (50,) (50,353) 

事實上sigma_los_beta是我單獨評估,並塑造(50,353,50)和那些353是我必須有數據的數組。

如何將此函數轉換爲與plot_trisurf其他條目兼容的表單?

對不起,但我不能提供一個最小的工作代碼,因爲dv,v和u是數據。 非常感謝您的幫助。乾杯

+0

你可以嘗試切片?你的示例代碼中有很多未定義的變量。不理解什麼是一切都很難幫助。 – tnknepp

回答

0

此代碼)的基礎上trisurf演示 http://matplotlib.org/examples/mplot3d/trisurf3d_demo.html

我添加了一個函數make_colormap(基於SO Create own colormap using matplotlib and plot color scale

還增加一個序列w = TAN(-x * Y),其產生基於該功能的色彩圖,灰度。
你可以玩cdict的結構來增加更多的顏色,但我認爲灰度是一個很好的概念證明...

對不起,我不能直接與你的例子,由於缺乏最小的工作代碼。

from mpl_toolkits.mplot3d import Axes3D 
from matplotlib import cm 
import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib.colors as mcolors 

################### 

def make_colormap(seq): 
    """Return a LinearSegmentedColormap 
    seq: a sequence of floats and RGB-tuples. The floats should be increasing 
    and in the interval (0,1). 
    """ 
    #% 
    cdict = {'red': [], 'green': [], 'blue': []} 

    # make a lin_space with the number of records from seq.  
    x = np.linspace(0,1, len(seq)) 
    #% 
    for i in range(len(seq)): 
     segment = x[i] 
     tone = seq[i] 
     cdict['red'].append([segment, tone, tone]) 
     cdict['green'].append([segment, tone, tone]) 
     cdict['blue'].append([segment, tone, tone]) 
    #% 
    return mcolors.LinearSegmentedColormap('CustomMap', cdict) 


############################# 



n_angles = 36 
n_radii = 8 

# An array of radii 
# Does not include radius r=0, this is to eliminate duplicate points 
radii = np.linspace(0.125, 1.0, n_radii) 

# An array of angles 
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False) 

# Repeat all angles for each radius 
angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1) 

# Convert polar (radii, angles) coords to cartesian (x, y) coords 
# (0, 0) is added here. There are no duplicate points in the (x, y) plane 
x = np.append(0, (radii*np.cos(angles)).flatten()) 
y = np.append(0, (radii*np.sin(angles)).flatten()) 

# Pringle surface 
z = np.sin(-x*y) 



w = np.tan(-x*y) 
colors = make_colormap(w) 



fig = plt.figure() 
ax = fig.gca(projection='3d') 

ax.plot_trisurf(x, y, z, cmap=colors, linewidth=0.2) 

plt.show() 
+0

非常感謝PabTorre。然而,如果我嘗試在我的代碼中評估你的w的等價物,這是驅動3D表面着色的原因,我會得到廣播錯誤。如果你檢查我的'LikeBeta'函數,你會注意到我用三個相同長度的數組來調用它。但是,該函數使用不同形狀的數組,這會導致廣播錯誤。我無法解決這個問題。你知道我該如何解決這個問題? – andrea

+0

當我嘗試運行你的函數時,r0_array沒有被定義,那個數組的tge結構是什麼? – PabTorre

5

This回答解決了4D面積的問題。它使用matplotlib的plot_surface函數而不是plot_trisurf

基本上你想要將你的x,y和z變量重塑成同一維度的二維數組。要將第四維添加爲色彩映射表,您必須提供與您的軸變量維度相同的另一個二維數組。

下面是帶有對應於x值的顏色圖的3d圖的示例代碼。 facecolors參數用於根據您的喜好更改顏色映射。請注意,其值是從matplotlib.cm.ScalarMappable類中的to_rgba()函數獲取的。

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

# domains 
x = np.logspace(-1.,np.log10(5),50) # [0.1, 5] 
y = np.linspace(6,9,50)    # [6, 9] 
z = np.linspace(-1,1,50)   # [-1, 1] 

# convert to 2d matrices 
Z = np.outer(z.T, z)  # 50x50 
X, Y = np.meshgrid(x, y) # 50x50 

# fourth dimention - colormap 
# create colormap according to x-value (can use any 50x50 array) 
color_dimension = X # change to desired fourth dimension 
minn, maxx = color_dimension.min(), color_dimension.max() 
norm = matplotlib.colors.Normalize(minn, maxx) 
m = plt.cm.ScalarMappable(norm=norm, cmap='jet') 
m.set_array([]) 
fcolors = m.to_rgba(color_dimension) 

# plot 
fig = plt.figure() 
ax = fig.gca(projection='3d') 
ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False) 
ax.set_xlabel('x') 
ax.set_ylabel('y') 
ax.set_zlabel('z') 
fig.canvas.show() 

我引用(和其他人)的回答中提到,您應該正常化的第四維的數據。看起來,這可以通過像我在代碼示例中那樣顯式設置色彩圖的限制來避免。

+0

太棒了!但正如我在這個問題中寫的,我的主要問題在於評估第四維數組。按照你的回答和我的代碼,我應該寫'color_dimension = LikeBeta(y,range(50),range(50))',即len(50)數組。它的元素在'LikeBeta'中評估,它是y的函數,x和z的索引,它使用sigma_los_beta的組件,一個(50,353,50)數組。這導致了我提到的廣播問題。一旦我解決了這個問題,我可以將你的建議應用於如何着色表面。有關如何解決這個問題的任何想法?謝謝 – andrea

+0

你能否提供關於'LikeBeta'函數中未知數的細節?例如。類型和維度如下:'r0_array,cst,dv,u,v'。如果沒有辦法模擬這個問題,就很難找出問題所在。重要的是該函數應該返回一個與軸變量維數相同的數組。另外,你打算執行矩陣還是元素乘法? – Frik

+0

對不起,你是對的。 'r0_array'是'= x','cst'只是一個浮點數,'dv','u','v'都是len 353(這些都是數據點)的numpy.array。所以,爲了簡單起見,您還可以刪除這兩行代碼,並簡單地: 'def LikeBeta(rho0,r0,beta): M0 = 10 ** rho0 * x [r0] ** 3 I = M0 * sigma_los_beta [beta::r0] return I'其中'sigma_log_beta'是一個形狀的np.array(50,353,50)。鑑於我將整個數組「sigma_los_beta [beta,:,r0]'乘以標量,因此它是元素明智的 – andrea

相關問題