关于matplotlib:(python)使用colormap作为第4维绘制xd,y,z函数的3d曲面 您所在的位置:网站首页 matplotlib曲面图 关于matplotlib:(python)使用colormap作为第4维绘制xd,y,z函数的3d曲面

关于matplotlib:(python)使用colormap作为第4维绘制xd,y,z函数的3d曲面

2024-07-13 07:12| 来源: 网络整理| 查看: 265

(python) plot 3d surface with colormap as 4th dimension, function of x,y,z

我正在尝试绘制3d曲面,其中三个维度中的每个维度都在单独的值数组中,并且每个坐标处的曲面着色是x,y,z的函数。 一种numpy.pcolormesh,但是是4D而不是3D的。 3D图由下式给出:

123456789from 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)

哪里

123456def 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可能是错误的,但问题出在其他地方。 我收到以下错误:

123----> 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是数据。 非常感谢您的帮助。 干杯

相关讨论 您可以尝试切片吗? 您的示例代码中有很多未定义的变量。 如果不了解一切,很难提供帮助。

该答案解决了4d表面绘图问题。它使用matplotlib的plot_surface函数而不是plot_trisurf。

基本上,您希望将x,y和z变量重塑为相同尺寸的2d数组。要将第四个尺寸添加为颜色图,必须提供另一个尺寸与轴变量相同的2d数组。

以下是3d图的示例代码,其色图对应于x值。 facecolors参数用于根据您的喜好更改颜色图。请注意,它的值是从matplotlib.cm.ScalarMappable类中的to_rgba()函数获取的。

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

相关讨论 精彩!但是,正如我在问题中所写的那样,我的主要问题在于对第四维数组的评估。按照您的答案和我的代码,我应该写color_dimension = LikeBeta(y,range(50),range(50)),即len(50)数组。它的元素在LikeBeta中求值,x是x的函数,使用x和z的索引,其中使用(50,353,50)数组sigma_los_beta的组件。这导致了我提到的广播问题。解决此问题后,我可以将您的建议应用于如何对表面着色。关于如何解决此问题的任何想法?谢谢 您能否在LikeBeta函数中提供有关未知数的详细信息?例如。类型和尺寸如下:r0_array, cst, dv, u, v。如果没有模拟方法,很难查明问题。重要的是该函数应返回与轴变量尺寸相同的数组。另外,您打算执行矩阵乘法还是逐元素乘法? 对不起,你说得对。 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是形状为(50,353,50)的np.array。假设Im将整个数组sigma_los_beta[beta,:,r0]乘以标量,则按元素 由于元素级乘法中的大小不匹配而导致错误。逐行跟踪功能中的输出尺寸,以查看需要在何处应用更改。我无法简单地更改功能以纠正失配错误,因为我不知道您希望实现什么目标。看一下numpy.repeat,求和时可能只需要沿一个维度进行。 我设法通过使colors成为具有列表理解的3D数组来解决数组维数问题。新问题:如何从3D阵列创建自定义颜色图?显然,上述答案中的minn和maxx不适用于3D阵列。如何创建从3D数组到颜色图的可映射对象?谢谢 我仍然在这里缺少一些东西。这被标记为正确,但是在此示例中,着色似乎仍然不是基于某些函数F(X,Y,Z)? 在这里,它只是F(X,Y,Z)=X。当然,您可以根据需要进行更改。注释试图解释。。请参见color_dimension变量。 @Frik非常感谢您的回答,对我很有帮助。请在下面查看我的答案,以对normalize方面和相关代码发表评论。

该代码基于trisurf演示 http://matplotlib.org/examples/mplot3d/trisurf3d_demo.html

我添加了一个基于make的功能make_colormap(),使用matplotlib创建自己的颜色图并绘制色标

还添加了一个序列w = tan(-x * y),该序列基于该函数生成灰度的颜色图。 您可以使用cdict的构造为它添加更多颜色,但是我认为灰度可以很好地证明概念...

抱歉,由于缺少最少的工作代码,因此我无法直接处理您的示例。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667from 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() 相关讨论 非常感谢PabTorre。但是,如果我尝试在代码中评估与您的w等效的值(这是驱动3D表面着色的原因),则会出现广播错误。如果检查我的LikeBeta函数,您会注意到Im调用了三个具有相同长度的数组。但是,该函数使用不同形状的数组,这会导致广播错误。我无法解决这个问题。你知道我该怎么解决吗? 当我尝试运行您的函数时,未定义r0_array,该数组的tge结构是什么?

非常感谢@Frik的出色回答,它帮助我实现了OP要求的类似情节。

但是,我发现可以对代码进行一些简化,并且可能会引起人们的兴趣。片段和图如下。

12345678910111213import matplotlib.pyplot as plt # This import registers the 3D projection, but is otherwise unused. from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import from mpl_toolkits.mplot3d.axes3d import get_test_data import numpy as np fig, ax = plt.subplots(subplot_kw={'projection': '3d'}) X, Y, Z = get_test_data(0.05) C = np.linspace(-5, 5, Z.size).reshape(Z.shape) scamap = plt.cm.ScalarMappable(cmap='inferno') fcolors = scamap.to_rgba(C) ax.plot_surface(X, Y, Z, facecolors=fcolors, cmap='inferno') fig.colorbar(scamap) plt.show()

最后,我还想评论@Frik的内容:

The answer I referenced (and others) mentions that you should normalize your fourth dimension data. It seems that this may be avoided by explicitly setting the limits of the colormap as I did in the code sample.

我发现这句话是不正确的。确实,如果人们看一下to_rgba,就会发现有一个norm关键字,默认情况下将其设置为True。这正是进行标准化的地方。还包括以下语句:

If norm is False, no normalization of the input data is performed, and it is assumed to be in the range (0-1).

您确实希望数据位于(0-1)中。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有