我想用个性化的颜色图绘制有限元模拟结果的图像。
我一直在尝试使用tricontourf将其绘制如下:

    #Z = self.phi.compute_vertex_values(self.mesh)
    Z = np.mod(self.phi.compute_vertex_values(self.mesh),2*np.pi)
    triang = tri.Triangulation(*self.mesh.coordinates().reshape((-1, 2)).T,
                               triangles=self.mesh.cells())
    zMax = np.max(Z)
    print(zMax)

    #Colormap creation
    nColors = np.max(Z)*200/(2*np.pi)
    phiRange = np.linspace(0,zMax,nColors)
    intensity = np.sin(phiRange)**2
    intensityArray = np.array([intensity, intensity, intensity])
    colors = tuple(map(tuple, intensityArray.T))
    self.cm = LinearSegmentedColormap.from_list("BAM", colors, N=nColors)

    #Figure creation
    fig, ax = plt.subplots()
    levels2 = np.linspace(0., zMax,nColors)

    cax = ax.tricontourf(triang, Z,levels=levels2, cmap = self.cm) #plot of the solution
    fig.colorbar(cax)

    ax.triplot(triang, lw=0.5, color='yellow') #plot of the mesh

    plt.savefig("yolo.png")
    plt.close(fig)


它给出了结果:
python - 使用Matplotlib Tricontourf的相图-LMLPHP

如您所见,当存在模数时,相位从2pi变为0,这是tricontourf带来的麻烦。

解决的第一个想法是直接在Z阶段工作。问题是,如果这样做,我需要创建一个更大的色图。最终,如果我想要正确的颜色分辨率,则相位将非常大,因此色图也将如此。此外,我希望右侧的色图中只有一个句点(就像第一个图一样)。
python - 使用Matplotlib Tricontourf的相图-LMLPHP

知道我如何能像第二个图一样获得具有第二个图的色图,而又不创建非常大且昂贵的色图吗?

编辑:我写了一个小的代码,它是开箱即用的:它重现了我遇到的问题,我也尝试将Thomas Kuhn的答案应用于我的前期问题。但是,颜色栏似乎存在一些问题...知道如何解决此问题吗?

import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import numpy as np
import matplotlib.colors as colors

class PeriodicNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, clip=False):
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.vmax], [0, 1]

        return np.ma.masked_array(np.interp(
            np.mod(value-self.vmin, self.vmax-self.vmin),x,y
        ))

# Create triangulation.
x = np.asarray([0, 1, 2, 3, 0.5, 1.5, 2.5, 1, 2, 1.5])
y = np.asarray([0, 0, 0, 0, 1.0, 1.0, 1.0, 2, 2, 3.0])
triangles = [[0, 1, 4], [1, 2, 5], [2, 3, 6], [1, 5, 4], [2, 6, 5], [4, 5, 7],
             [5, 6, 8], [5, 8, 7], [7, 8, 9]]
triang = mtri.Triangulation(x, y, triangles)
cm = colors.LinearSegmentedColormap.from_list('test', ['k','w','k'], N=1000)

#Figure 1 : modulo is applied on the data :
#Results : problem with the interpolation, but the colorbar is fine
z = np.mod(10*x,2*np.pi)
zMax = np.max(z)
levels = np.linspace(0., zMax,100)

fig1, ax1 = plt.subplots()
cax1=ax1.tricontourf(triang, z,cmap = cm,levels= levels)
fig1.colorbar(cax1)
plt.show()

#Figure 2 : We use the norm parameter with a custom norm that does the modulo
#Results : the graph is the way it should be but the colormap is messed up
z = 10*x
zMax = np.max(z)
levels = np.linspace(0., zMax,100)

fig2, ax2 = plt.subplots()
cax2=ax2.tricontourf(triang, z,levels= levels,norm = PeriodicNormalize(0, 2*np.pi),cmap = cm)
fig2.colorbar(cax2)
plt.show()


最后一个解决方案是像我上面所做的那样:创建一个更大的色图,该色图达到zmax,并且每2 pi周期一次。但是颜色条不会很好...

结果如下:
python - 使用Matplotlib Tricontourf的相图-LMLPHP
python - 使用Matplotlib Tricontourf的相图-LMLPHP

最佳答案

我猜测您的问题是由于在调用tricontourf之前对数据使用模数引起的(我想是对数据进行一些插值,然后将插值后的数据映射到颜色图)。而是可以将norm传递给tricontourf函数。在this tutorial之后编写一个小类,您可以使规范处理数据的模数。由于您的代码本身无法运行,因此我提出了一个更简单的示例。希望这适用于您的问题:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors

class PeriodicNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, clip=False):
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.vmax], [0, 1]

        return np.ma.masked_array(np.interp(
            np.mod(value-self.vmin, self.vmax-self.vmin),x,y
        ))

fig,ax = plt.subplots()
x,y = np.meshgrid(
    np.linspace(0, 1, 1000),
    np.linspace(0, 1, 1000),
)

z = x*10*np.pi
cm = colors.LinearSegmentedColormap.from_list('test', ['k','w','k'], N=1000)
ax.pcolormesh(x,y,z,norm = PeriodicNormalize(0, 2*np.pi), cmap = cm)
plt.show()


结果看起来像这样:

python - 使用Matplotlib Tricontourf的相图-LMLPHP

编辑:

当您从ContourSet返回的tricontourf跨越整个阶段时,而不仅仅是第一个[0,2pi],因此会为该整个范围创建颜色栏,这就是为什么您看到颜色图会重复多次的原因。我不太确定我是否了解刻度线的创建方式,但我猜测要使该自动化功能正确运行将是一项很大的工作。相反,我建议像“ this tutorial”中那样手动生成一个颜色条。但是,这要求您创建自己放置颜色条的轴(cax)。幸运的是,有一个名为matplotlib.colorbar.make_axes()的函数可以为您完成此任务(全部感谢this answer)。因此,请使用以下两行代替原始的colorbar命令:

cax,kw = mcbar.make_axes([ax2], location = 'right')
cb1 = mcbar.ColorbarBase(cax, cmap = cm, norm = norm, orientation='vertical')


要获得这张照片:

python - 使用Matplotlib Tricontourf的相图-LMLPHP

关于python - 使用Matplotlib Tricontourf的相图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52202032/

10-10 19:11